Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Anyone know how to run a profile script in the runspace?

77 views
Skip to first unread message

CodeSlinger

unread,
Jun 30, 2009, 12:58:00 PM6/30/09
to

I have my own hosting application, with UI and RawUI implemented, that
generally works fine and want the runspace to run profiles before I use the
pipeline.

If there is no concept of running them for me I want to load certain scripts
and run them myself. I have tried using RunspaceInvoke(myRunspace) with the
Profile variable set in the session and that does strange and unatural things
that I have been unable to debug or catch [puts up my dialog from within the
append call without returning to the mainform_load call].

I have tried the below code with variations on the path separation
characters. As soon as I execute the append statement, my forms dialog comes
up and I never actually make it to the 2nd statement which creates the
RunspaceInvoke object. My call stack shows me in some werid kind of inner
message loop with the last call being
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop.

mRunspace.RunspaceConfiguration.InitializationScripts.Append(new
ScriptConfigurationEntry(@"C:\\Users\\[MyUserid]\\Documents\\WindowsPowerShell\\Microsoft.PowerShell_profile.ps1", "Profile script"));
RunspaceInvoke lRunspaceInvoke = new RunspaceInvoke(mRunspace);

The MSDN doc is no help as it refers to skin and bone examples that do not
use these methods. I would love to know how to use RunspaceInvoke,
RunspaceConfiguration, ScriptConfigurationEntry etc. in general but
specifically to run some profile scripts. Seems these methods will get me
what I want but how to use them is not readily apparent to me or does not
work.

Thanks, Dave

CodeSlinger

unread,
Jun 30, 2009, 1:14:01 PM6/30/09
to

OK the below actually worked but I would love still to see more info on the
above methods if anyone can help orient...Dave

// open the runspace and run the profile
mRunspace.Open();


RunspaceInvoke lRunspaceInvoke = new RunspaceInvoke(mRunspace);

lRunspaceInvoke.Invoke(@"C:\\Users\\[myuserid]\\Documents\\WindowsPowerShell\\Microsoft.PowerShell_profile.ps1");

Joel Bennett

unread,
Jun 30, 2009, 5:03:13 PM6/30/09
to

There is no concept of running profiles for you automatically.

Let me start by pointing you at a blog post I wrote about
RunspaceConfiguration. My conclusion was that you can't actually create
a custom RunspaceConfiguration.

http://huddledmasses.org/is-powershell-shellid-too-big-a-burden/

As far as I can tell, profile scripts are not InitializationScripts. The
documentation on this stuff leaves MUCH to be desired, of course: there
are NO samples, and for the most part I suspect the only people who
understand the docs work at Microsoft ;)

I can point you to what I did, but it's rather complicated compared to
what you actually "have" to do (especially if you're not trying to
create an interactive host):

http://poshconsole.codeplex.com/SourceControl/changeset/view/30329#356218

But I've talked to most of the guys that have worked on PowerShell
hosts, and as far as I know, we're all agreed that you have to just run
the profile script(s) yourself, and if you want it to be "like
powershell.exe" then you need to make sure you:

1) dot-source them
2) don't put them in the history

--
Joel

CodeSlinger

unread,
Jun 30, 2009, 5:55:03 PM6/30/09
to

Thanks Joel,

As I posted in the earlier reply to myself, I did manage to run my scripts
by invoking them in the runspace and was quite happy till I realized that
anything they did had gone out of scope when I invoked my main script in the
pipeline create. My application is basically running a script and saving the
output and I do not have an interactive shell but have implemented UI and
RawUI.

I'm quite new to PowerShell and understand that when you "dot-source" one
script from another it is like you included the cmdlets in your outer script
and so circumvent the scope issue compared to invoking it. What I'm not sure
about is how, within a single pipeline, to run some profile scripts ahead of
my main script I want to run. Basically I guess I would have to "dot-source"
any profile script I wanted to run and then add my own script to the pipeline
so will play around with that. I seem to remember I could not add multiple
scripts as only the last was executed and produced output. Ideally, there
would be some way to "dot-source" the profile script in the runspace and have
that environment presented to the pipeline as I will ultimately run several
scripts one by one but would love to share the runspace and a common profile
execution. Maybe not possible. I will try ways to do something with the
runspace as well. Do you know if there any concept of scope in the runspace
that is inerited by the pipeline or is sessionstate pretty much all it gets?

Yes, the documentation is woefully inadequate when a method such as
RunspaceFactory.CreateRunspace gives you the pearl of wisdom that merely says
it creates a Runspace (duh) and refers you to a skin and bones example that
does not use that method much less any of the other signatures that have the
desired optional parameters. And no intellisense... The whole concept of
PowerShell is generally great though!

Would love your .02 on my other post regarding BufferSize, line wrapping and
what I feel is a hosting bug where PS pads out most WriteLine calls with
blanks to meet the BufferSize.

Thanks again, Dave

CodeSlinger

unread,
Jun 30, 2009, 6:26:01 PM6/30/09
to

Well I sort of got it working with the following but get the horrible cmd.exe
shell type black screen flash when I run the scripts which include one user
profile and my main script I want to run. Any way to get rid of that flash???
Dave

// add the profile scripts if any
foreach (FileInfo lProfileFileInfo in lProfileFileInfos)
{
lScriptName = string.Format(". '{0}'", lProfileFileInfo.FullName);
mPipeline.Commands.AddScript(lScriptName, false); // does not work if
local scope
}

// add our main script
lScriptName = string.Format(". '{0}'", pScriptCommand);
mPipeline.Commands.AddScript(lScriptName, false); // do not use local scope
here either but does not seem to matter either way

Joel Bennett

unread,
Jun 30, 2009, 10:51:08 PM6/30/09
to

Another way to do it is just to string them all together as one script.
From that CommandBuffer source I linked to earlier:


List<string> existingProfiles = new List<string>();

string myDocs =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

foreach (var path in new[]{
Path.GetFullPath(Path.Combine(Environment.SystemDirectory,
@"WindowsPowerShell\v1.0\profile_exit.ps1")),
Path.GetFullPath(Path.Combine(Environment.SystemDirectory,
@"WindowsPowerShell\v1.0\PoshConsole_profile_exit.ps1")),
Path.GetFullPath( Path.Combine( myDocs,
@"WindowsPowerShell\profile_exit.ps1")),
Path.GetFullPath( Path.Combine( myDocs,
@"WindowsPowerShell\PoshConsole_profile_exit.ps1")),
}) {
if (File.Exists(path)) {
existingProfiles.Add(path);
}
}


Then, you add your script to that, and turn them all into a single
script. Something like this:


mPipeline.Commands.AddScript(
". '" +
String.Join("'\n. '", existingProfiles.ToArray()) +
"'\n" +
yourScriptFullName );

If you're getting a console window flash, it's probably because you're
running a legacy console app in your script. You can't avoid opening a
"real" (read "legacy") console window, exactly, but you CAN hide it.

I released that part of PoshConsole under a LOT of different Open Source
licenses, including BSD or MIT, so you should feel free to borrow my
NativeConsole.cs ...

http://poshconsole.codeplex.com/SourceControl/changeset/view/30329#139099

--
Joel

CodeSlinger wrote:
> Well I sort of got it working with the following but get the horrible cmd.exe
> shell type black screen flash when I run the scripts which include one user
> profile and my main script I want to run. Any way to get rid of that flash???
> Dave

...

...

CodeSlinger

unread,
Jun 30, 2009, 11:43:01 PM6/30/09
to

I am able to invoke the profile script from the RunspaceInvoke object but
found you have to explicity fetch the output and errors else execution is
delayed till the pipeline is invoked and you gt no output though the result
environemnt remains in scope. Also RunspaceInvoke.Invoke can throw vs. how
the pipeline worked. I had no luck adding an "Out-Default" cmdlet like you
can in the pipeline though I do like the idea of running the scripts at the
runspace level rather than each pipeline since I'm non interactive. I'll
experiment some more. Thanks!

And thanks for the offer on the nativeconsole. Indeed, I found out the
"flash" was not from my profile per se but rather from calling a WMI related
function I had defined in my profile. I thought it was due to the profile
since it only happened once and not on subsequent calls. I removed the
function out of the profile and just define and call the function in my main
script invoked by the pipeline, not the runspace, and still get the "flash"
there as well. Nothing to do with profiles. It was a snippet I picked up at
someone's WMI blog though I forget who...

### The call of this function flashes the first time it is executed but not
subsequent times
function Get-MyLoggedOnUsers
{
param([string]$Computer)
if ($computer -eq "")
{
$computer = hostname
}
Get-WmiObject Win32_LoggedOnUser -ComputerName $Computer | Select
Antecedent -Unique | %{"{0}/{1}" -f $_.Antecedent.ToString().Split(’"‘)[1],
$_.Antecedent.ToString().Split(’"‘)[3]}
}

"`nShow logged on users..."
Get-MyLoggedOnUsers


Bob Landau

unread,
Jul 1, 2009, 1:40:01 PM7/1/09
to

Joel or Dave,

If you read about_profiles the helpfile leads one to believe that
$pshome\profile.ps1 will be ran for all users and hosts. Have you tried this?
Based on what both you two are saying I'm taking that its up to the host to
run these explicitly.

just curious
bob

Bob Landau

unread,
Jul 1, 2009, 1:37:01 PM7/1/09
to

What is the threading model of your host? I suspect since its doesn't present
a UI you have it unmarked or free-threaded. The entry point should be marked
as [STAThread]. The behavior you've mentioned below leads me to believe you
are running in "native", free-threaded or whatever they now call it.

All UI code ends up using the good ol Windows Message pump eventually. I
would have thought a modal dialog would have behaved regardless however seem
to recall people having problems with the POSH Console host and WPF the
reason is its free-threaded.

> > characters. As soon as I execute the append statement, my forms dialog comes
> > up and I never actually make it to the 2nd statement which creates the
> > RunspaceInvoke object. My call stack shows me in some werid kind of inner
> > message loop with the last call being

CodeSlinger

unread,
Jul 1, 2009, 1:59:00 PM7/1/09
to

This is what I try to do per Lee's article at
http://www.leeholmes.com/blog/TheStoryBehindTheNamingAndLocationOfPowerShellProfiles.aspx
and other stuff I have read and so substitute a profile with my host name vs.
the Microsoft.PowerShell host name. - Dave

1. "All users" profile is loaded from "<Installation Directory>\profile.ps1"
2. "All users," host-specific profile is loaded from "<Installation
Directory>\Microsoft.PowerShell_profile.ps1"
3. Current user profile is loaded from "<My
Documents>\WindowsPowerShell\profile.ps1"
4. Current User, host-specific profile is loaded from "<My
Documents>\WindowsPowerShell\Microsoft.PowerShell_profile.ps1"

Dave

CodeSlinger

unread,
Jul 1, 2009, 2:12:01 PM7/1/09
to

I don't specifically set one so think I am MTA. I believe what was happening
is that I was tired and in fact was getting an unhandled exception when
trying to work with the runspace and that threw me back into the message loop
but that was quite a bit of code ago and with my monkey and typewriter
approach trying to get this to work without good documentation, I'm not
certain anymore. In any event, I am able to run profile(s) at the runspace
level now using the following for each profile I want to run but have to
manually grab the output and errors as well as catch for each profile
execution which is not as nice an environment as running a script in the
pipeline with the PSHost UI implemented where pretty much all output and
errors are delivered to you via the common WriteXXX methods. - Dave

Collection<PSObject> output = lRunspaceInvoke.Invoke(lScriptName, null, out
errors);

0 new messages