start powershell.exe inside a ps1-script with a predefined variable - powershell

so this is my first post here on stackoverflow :-) hm,... would think i operate with powershell as an "experienced beginner", written some nice-working scripts for OS-automation in the last 2 years. no programming-skills, only little bit of scripting to make my life as sysadmin easier.
currently i have a tricky problem - excuse me in case this was already solved in another thread, but didn´t find a solution to it.
here the purpose of the code:
enable a normal windows-user (not member of local admin-group) to execute some scripts with administrative rights.
switch current user to a user with admin-rights >> solved. created a pscredential-object ($pscreds). works good.
start an elevated powershell-session to have the ability to do admin-stuff >> solved. powershell.exe -verb RunAs bla bla. works good.
launch a fix-named script with admin-rights >> solved.
problem itself:
script-name is not always the same one.... i want to enable the code to use the path and name of current running script ($Myinvocation.Mycommand.Definition).
$x = $myinvocation.MyCommand.Definition
Start-Process powershell.exe -Credential $pscreds -ArgumentList {
Start-Process powershell.exe -Verb RunAs -ArgumentList {
start-process powershell.exe -ArgumentList (-file "$x")
}
}
how to modify the code that the variable $x at -file "$x" takes the value defined in first line?
i found a workaround by myself write the path & scriptname to a temp-file and read it back to $x with "get-content". but i didn´t like this ugly solution and hoped solve this in a better way.
thanks for help and best greetings from germany
Ralph

I think that without getting into a whole host of Windows Auth issues doing that inside one script, I'd stick to what you are already talking about as a kludge - Try letting the non-admin edit that $x value in a file they have access to. Then run a script on schedule with an admin account that reads the file.

Related

override ps1 script module function only working when launching script as admin

I'm currently working on a custom project using ps1 scripts and to achieve this the cleanest way possible I tried to use inheritance and override concepts.
For inheritance I used module functionality, thus I have a module.psm1 file providing mother's functions to children, everything working like a charm and making powershell script enough convenient for me.
About overriding concept, I am able to use a kind of overriding mechanism (not sure if override is the proper naming in this case, sorry if not) but it only works when my script is launched in Admin mode.
I guess my issue and question could be a bit tough, but I'll make it the clearest possible, let me know if you need further explanations.
I have a function A in module.psm1 which I can use in child.ps1 cause I properly made it usable using "Export-ModuleMember -Function A"
Inside this function A I use a function B which is not declared in module.psm1 but instead is declared in child.ps1. It's because A as a general behaviour which benefits several childs.ps1 but B needs to be child specific.
The main purpose is to have a clean, factorized code, allowing easy maintaining
When I don't launch in Admin mode it doesn't work, i.e it says "function B not find" while in admin mode everything is fine, plus there is no need to launch as admin in this particular context I'm talking about.
#module.psm1 #AKA mother
function A ($optionalParam=$null){B}
Export-ModuleMember -Function A
WORKING WAY
#child.ps1
Import-Module "Module\module.psm1"
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`" `"$args`"" -Verb RunAs; exit }
function B ($optionalParam=$null){#somecode}
And it works great... in Admin mode only.
NOT WORKING
#child.ps1
Import-Module "Module\module.psm1"
#if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`" `"$args`"" -Verb RunAs; exit }
function B ($optionalParam=$null){#somecode}
Q1. I'd like to know if "override" mecanism (or what I want to achieve) is possible or provided in powershell script.
Q2. And why how I'm proceeding is working in a case and not the other, i.e admin mode vs not admin.
Thanks a lot for your help

Powershell - How to use Start-Process to call file from share/pass args in single line

To preface this, I am self teaching and brand new to scripting in general, let alone powershell.
After a cumulative 12 hours, my Google fu has run out.
I had a series of programs tailored to different models of computer we support that ran a staged series of installers from a fileshare. The program would check to see if the tech deploying the software was running it as admin, if not, it used a Start-Process line to elevate and run again.
It worked flawlessly, but we wanted to see if we could remove the need for the tech to enter r to run the scripts from the share.
In trying to figure out how to add -executionpolicy bypass to the arg list for Start-Process, I've hit a wall.
It now errors on trying to call to the fileshare to retrieve the parent script, before getting to the point where I can troubleshoot the bypass can of worms.
Below is my rough framework, remember I'm self taught by googling and using tutorials point.
$principal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
if($principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
{
#usually I have a get-childitem | foreach-object loop here that runs the files from the folder one by one in a specific order,
#it also checks to see if msiexec is running or not before trying to load and install files using a if-else>do-while combo
}
else
{
Start-Process -FilePath "powershell" -ArgumentList "$('-File "\\server\dir\foo".ps1')$($MyInvocation.MyCommand.Name)$('""')" -Verb runAs
}#this calls to a script that is a 1:1 copy of the code in the if{} block
This returns an error from the -File parameter that says it can't call the file because it doesn't exist.
What am I doing wrong?
How do I pass -executionpolicy bypass as an additional arg without breaking it further?
Is there a better way to do this?
Is there a neater way to automate this?
Please help me geniuses of StackOverflow before I start gnawing on my keyboard.

Launch PowerShell script into new window while passing variables

I've been using the site for a while, searching through the questions and answers, trying to map them to my scenario, but I'm either missing something, or what I'm looking to do isn't possible (at least the way I'm trying to do it), hence I'm hoping for a push in the right direction. Thanks in advance for reading.
I've been working on a fairly sizeable automation project. My main script performs a number of tasks, and generally works well, and reliably. At one stage of the script, I execute another PowerShell script, which was written by another team. I call the script as follows:
.\DeployMySQLProvider.ps1 -AzCredential $asdkCreds `
-VMLocalCredential $vmLocalAdminCreds `
-CloudAdminCredential $cloudAdminCreds
-PrivilegedEndpoint $ERCSip `
-DefaultSSLCertificatePassword $secureVMpwd -AcceptLicense
When I call it this way, from my main script, it works fine, however, this script uses and registers a DLL file during it's deployment, and locks it until the PowerShell window and session is closed. At the end of my main script, I have a cleanup phase, which can't complete it's job because of this locked DLL.
My thoughts therefore, were to launch the 2nd script into a new PowerShell window and session, either using Start-Process or Invoke-Expression, but I just can't seem to get either right. Most of the variables I'm passing through to the 2nd script aren't just strings, which is probably where I'm falling over. They are a mix of usernames and passwords (secure strings) along with $ERCSip which is a string.
Should I be looking at Start-Process / Invoke-Expression, or something else entirely? When I was testing with Start-Process, I had the following defined, but couldn't get the ArgumentList side working correcly for me (blank below):
Start-Process "$pshome\powershell.exe" -PassThru -Wait `
-Verb RunAs -ErrorAction Stop -ArgumentList ""
Any pointers in the right direction would be much appreciated.
Thanks!
I've used something similar to this in my scripting:
$scriptpath="c:\pathto\deploysqlProvider"
$a = "$scriptpath\DeployMySQLProvider.ps1 -AzCredential $asdkCreds `
-VMLocalCredential $vmLocalAdminCreds `
-CloudAdminCredential $cloudAdminCreds
-PrivilegedEndpoint $ERCSip ` "
-DefaultSSLCertificatePassword $secureVMpwd -AcceptLicense
Start-Process -Verb runas -FilePath powershell.exe -ArgumentList $a -wait -PassThru ;
Not sure if you need it to runas admin or not (-verb runas).
I'd suggest you then look for the Powershell process and path. So that if you have to kill this separate process you can.

Powershell Quotes Use asisstance

Need some expert help from you guru's out there (after 3 days of trying on my own lol). Here the portion of my script that's failing:
$yy=(get-date).Year
Invoke-Command -ComputerName *ipaddress* -Credential $moveitcred {
move-item -path "C:\iCApps\Dev\LetterGenerator\Letters\FTS\EDMS\*.txt" -destination "C:\Moveitft\Dev\Letters\Outbound" -force
Start-Process -FilePath "C:\Program Files\7-Zip\7z.exe" -ArgumentList "a -y C:\Moveitft\Dev\Letters\archive\Letters$yy_.zip C:\Moveitft\Dev\Letters\Outbound\*.*"
}
The move works fine. AND the zip works fine, except when I want to include the the year varible ($yy) in the argument list. Powershell doesn't want to populate the variable to adjust the file name. Either it bombs out citing a $null, or the job completes with just a blank where the $yy should be.
If i run just $yy from the prompt, it does return the correct year value, so I'm guessing it an improper use of quotes. But after 3 days of googling and trying various combinations on my own, I'm throwing in the towel. Any help/guidance would be so GREATLY appreciated :)
Change Letters$yy_.zip to either
Letters$($yy)_.zip
or
Letters${yy}_.zip.
Both of them work.
See: PowerShell subexpression and PowerShell variable names.
The problem is not about quoting is about variable scope. Inside the scriptblock you are executing, powershell knows nothing about the $yy var. So you need to tell it where to obtain the value. You could do that using the argumentList parameter. I see that you already are doing that but you are doing it wrong (move-item doesn't support that parameter). Look the following examples to grasp the concept, I think with that you will solve your problem:
# this is fine and simple
$yy="Hello scriptblocks!"
Invoke-Command -ScriptBlock { "whatever you want to run that use the an external var. $yy" } -ArgumentList $yy
# this is incorrect
Invoke-Command -ScriptBlock { "whatever you want to run that use the an external var. $yyCarefulWithThisText" } -ArgumentList $yy
# this shows how you could resolve the variable when you want to put text around
Invoke-Command -ScriptBlock { "whatever you want to run that use the an external var. $($yy)CarefulWithThisText" } -ArgumentList $yy
# output1: whatever you want to run that use the an external var. Hello scriptblocks!
# output2: whatever you want to run that use the an external var.
# output3: whatever you want to run that use the an external var. Hello scriptblocks!CarefulWithThisText
Tried the above, thank you! I think this might boil down to powershell version. I'm trying to execute this on a server running powershell v2.0, against another 2012 Server.
I've shortened down the code to just the line in question (so I can "F8" it to test the results) Here it is:
Invoke-Command -ComputerName ipaddress -Credential $moveitcred {
Start-Process -FilePath "C:\Program Files\7-Zip\7z.exe" -argumentlist "a -y C:\Moveitft\Dev\Letters\archive\Letters${yy}.zip C:\Moveitft\Dev\Letters\Outbound*.*"
}
Both of your suggestions "work", in that the command processes, however its still not reading the variable correctly. Here's what I get as a resultant .zip
The reason I'm thinking its powershell, is becuase if I copy/paste the same command into powershell v4.0 on my own production machine, you can instantly see by the color coding that the "$yy" is being considered a variable because it turns red - and then the code works ok on from my PS4.0 machine.
On the PSv2.0 server i'm trying to get this to run from, that same line for "-argumentlist" appears all maroon/brown - including the $yy portion. So its kind of a hint whether it will work or not for me.

How to open Powershell Console Window from Powershell

I am writing a script to use multiple plink (PuTTY) sessions as a Windows version of clusterssh. I am stuck however because I want to open multiple Powershell windows from powershell. When I type the command for powershell, it opens a new session. This is similar to typing bash in bash. I want multiple physical windows opening.
I tried -windowstyle as well as the other args to no avail. I was wondering if there is a way you know of. I really appreciate your help. I looked and didn't find anything already here. Thanks for your time.
This will open a new window.
Either:
start-process powershell
Or:
start powershell
if you are trying to open a new window and launch a new script:
start powershell {.\scriptInNewPSWindow.ps1}
This will do it:
Invoke-Item C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
This works for me:
$argList = "-file `"$Location\script.ps1`""
Start-Process powershell -argumentlist $argList
(The backticks are necessary. This can be copied outright.) Variables can be used in the "-file" parameter (such as one set at the beginning of the script to reflect the location of the file) and spaces can appear in the variable due to the backticks.
Edited to use a two-line solution (the "$argList" variable) because PowerShell can mangle things otherwise.
To start Powershell 6 from a PS console start pwsh might do the trick.
It starts in the same folder.
(I haven't delved into it but I guess PS6's pwsh.exe has to be in the path for it to work.)