Just starting with Powershell and need some pointers

Discussion in 'Scripting' started by adric, Dec 13, 2019.

  1. adric

    adric MDL Addicted

    Jul 30, 2009
    958
    739
    30
    #1 adric, Dec 13, 2019
    Last edited: Dec 13, 2019
    When I run powershell from a batch file as described by @abbodi1406 here, it is not recognized:

    'powershell' is not recognized as an internal or external command,
    operable program or batch file.

    Powershell is there, but I'm somewhat clueless in using it except for simple cmds. I managed
    to enable it with Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force
    and I can start it from the Run Box, but that's about it. If I run the command from the powershell prompt, I get:

    powershell : The term 'powershell' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again
    At line:1 char:1
    + powershell -nop -ep bypass -c "&{$doc = [xml](Get-Content '%_f%'); $n ...
    + ~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (powershell:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    .ps1 cmds won't start either and end up in notepad when executed. The environment for
    powershell doesn't seem to be set up correctly to simply launch scripts. or to run it from batch files.

    Thanks for any pointers to get me started..
     
  2. abbodi1406

    abbodi1406 MDL KB0000001

    Feb 19, 2011
    13,149
    64,384
    340
    What's the batch file looks like exactly?

    unless you mess with Path environment variable, powershell should run from anywhere
     
  3. Thomas Dubreuil

    Thomas Dubreuil MDL Senior Member

    Aug 29, 2017
    361
    606
    10
    Exactly.
    More probably wrong syntax
    One simple way I use to circumvent potential Path environment problems is to set powershell (and windir) variable in script.
    Code:
    set "windir=C:\Windows"
    set "PScommand=%windir%\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass"
    I also add checks for robocopy and user name (borrowed this from blackbird script), like
    Code:
    set "UserName=%username%"
    if not defined UserName ( goto :Error_No_User )
    if not exist "C:\Windows\System32\robocopy.exe" ( goto :Error_No_Robocopy )
    From here I can do pretty much everything safely
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  4. adric

    adric MDL Addicted

    Jul 30, 2009
    958
    739
    30
    #4 adric, Dec 14, 2019
    Last edited: Dec 15, 2019
    (OP)
    Code:
    @echo off
    rem Toggle powershell on and off
    rem Get-ExecutionPolicy -List
    rem Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force
    rem Set-ExecutionPolicy -Scope CurrentUser Undefined
    
    rem Del SSU from u1 (KB2919442) and leave SSU from u3 (KB3173424). Use
    rem Regscanner to check PERM status. Use package id for find string:
    rem Package_for_KBxxxxxxx~31bf3856ad364e35~amd64~~n.n.n.n\Owners
    rem Update reg with nsudo if needed and then update mum permanency to removable
    
    rem Package_for_KB2919442~31bf3856ad364e35~amd64~~6.3.1.8  reg + mum
    rem Package_for_KB3173424~31bf3856ad364e35~amd64~~6.3.1.0  reg + mum keep
    rem Package_for_KB4504418~31bf3856ad364e35~amd64~~6.3.1.1  mum
    rem Package_for_KB4512938~31bf3856ad364e35~amd64~~6.3.1.1  mum
    rem Package_for_KB4521864~31bf3856ad364e35~amd64~~6.3.1.1  mum
    rem Package_for_KB4524445~31bf3856ad364e35~amd64~~6.3.1.0  mum current
    
    set _p=Package_for_KB4521864~31bf3856ad364e35~amd64~~6.3.1.1
    
    set _f=%SystemRoot%\servicing\Packages\%_p%.mum
    
    powershell -nop -ep bypass -c "&{$doc = [xml](Get-Content '%_f%'); $node = $doc.assembly.package | where { $_.permanence -eq 'permanent' }; if ($node -ne $null) { $node.permanence = 'removable' }; $doc.save('%_f%')}"
    
    dism /Online /NoRestart /Remove-Package /PackageName:%_p%
    rem %windir%\Sysnative\dism /Online /NoRestart /Remove-Package /PackageName:%_p%
    
    If I use start powershell, it works. If I type powershell in a cmd prompt, I get 'not recognized'

    I just looked at the path string and see this:
    Code:
    C:\Windows\System32\WindowsPowerShell\v1.0";C:\Windows.........
    
    Dir on that path works, but apparently the trailing " is not always ignored as with the dir cmd. Removing the " fixed the path to run powershell from anywhere. No idea where the " came from.
     
  5. adric

    adric MDL Addicted

    Jul 30, 2009
    958
    739
    30
    #5 adric, Dec 14, 2019
    Last edited: Dec 14, 2019
    (OP)
    Any idea why the following doesn't work? Seems to be releated to special chars in the path. I can cd with other dirs.
    Code:
    PS U:\> cd $all
    cd : Cannot process argument because the value of argument "path" is null.
    Change the value of argument "path" to a non-null value.
    At line:1 char:1
    + cd $all
    + ~~~~~~~
        + CategoryInfo          : InvalidArgument: (:) [Set-Location], PSArgumentN
       ullException
        + FullyQualifiedErrorId : ArgumentNull,Microsoft.PowerShell.Commands.SetLo
       cationCommand
    
    PS U:\> cd backups
    PS U:\backups>
    Edit: Found it. Need to use backtick (`) before the special character
    PS U:\> cd `$All
    PS U:\$All>

    Also is it okay to change the association for .ps1 to powershell.exe? Mine is opening the file in notepad and not executing it, or is this a safety feature to keep powershell scripts from running?

    Maybe I shouldn't change it.
     
  6. adric

    adric MDL Addicted

    Jul 30, 2009
    958
    739
    30
    Code:
    set "windir=C:\Windows"
    
    Isn't %windir% a system variable with the same value or is there a specific reason for setting this locally?
     
  7. Thomas Dubreuil

    Thomas Dubreuil MDL Senior Member

    Aug 29, 2017
    361
    606
    10
    Maybe because varialbe $all is not defined (nul), and that you need to set it with $all = "C:\any\path"

    Yes it is default
    In context menu, you have "run with powershell" to run script,
    "open" opens notepad and "edit" opens Powershell ISE (powershell editor) for editing file.

    Code:
    Windows Registry Editor Version 5.00
    
    [HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1]
    "EditFlags"=dword:00020000
    "FriendlyTypeName"=hex(2):40,00,22,00,25,00,73,00,79,00,73,00,74,00,65,00,6d,\
      00,72,00,6f,00,6f,00,74,00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,\
      33,00,32,00,5c,00,77,00,69,00,6e,00,64,00,6f,00,77,00,73,00,70,00,6f,00,77,\
      00,65,00,72,00,73,00,68,00,65,00,6c,00,6c,00,5c,00,76,00,31,00,2e,00,30,00,\
      5c,00,70,00,6f,00,77,00,65,00,72,00,73,00,68,00,65,00,6c,00,6c,00,2e,00,65,\
      00,78,00,65,00,22,00,2c,00,2d,00,31,00,30,00,33,00,00,00
    
    [HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\DefaultIcon]
    @="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell_ise.exe\",1"
    
    [HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell]
    @="Open"
    
    [HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\0]
    "MUIVerb"=hex(2):40,00,22,00,25,00,73,00,79,00,73,00,74,00,65,00,6d,00,72,00,\
      6f,00,6f,00,74,00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,\
      00,5c,00,77,00,69,00,6e,00,64,00,6f,00,77,00,73,00,70,00,6f,00,77,00,65,00,\
      72,00,73,00,68,00,65,00,6c,00,6c,00,5c,00,76,00,31,00,2e,00,30,00,5c,00,70,\
      00,6f,00,77,00,65,00,72,00,73,00,68,00,65,00,6c,00,6c,00,2e,00,65,00,78,00,\
      65,00,20,00,22,00,2c,00,2d,00,31,00,30,00,38,00,00,00
    
    [HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\0\Command]
    @="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" \"-Command\" \"if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & '%1'\""
    
    [HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\Edit]
    "NoSmartScreen"=""
    
    [HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\Edit\Command]
    @="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell_ise.exe\" \"%1\""
    
    [HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\Open]
    
    [HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\Open\Command]
    @="\"C:\\Windows\\System32\\notepad.exe\" \"%1\""
    
    [HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\runas]
    "HasLUAShield"=""
    
    [HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\runas\command]
    @=hex(2):70,00,6f,00,77,00,65,00,72,00,73,00,68,00,65,00,6c,00,6c,00,2e,00,65,\
      00,78,00,65,00,20,00,22,00,2d,00,43,00,6f,00,6d,00,6d,00,61,00,6e,00,64,00,\
      22,00,20,00,22,00,69,00,66,00,28,00,28,00,47,00,65,00,74,00,2d,00,45,00,78,\
      00,65,00,63,00,75,00,74,00,69,00,6f,00,6e,00,50,00,6f,00,6c,00,69,00,63,00,\
      79,00,20,00,29,00,20,00,2d,00,6e,00,65,00,20,00,27,00,41,00,6c,00,6c,00,53,\
      00,69,00,67,00,6e,00,65,00,64,00,27,00,29,00,20,00,7b,00,20,00,53,00,65,00,\
      74,00,2d,00,45,00,78,00,65,00,63,00,75,00,74,00,69,00,6f,00,6e,00,50,00,6f,\
      00,6c,00,69,00,63,00,79,00,20,00,2d,00,53,00,63,00,6f,00,70,00,65,00,20,00,\
      50,00,72,00,6f,00,63,00,65,00,73,00,73,00,20,00,42,00,79,00,70,00,61,00,73,\
      00,73,00,20,00,7d,00,3b,00,20,00,26,00,20,00,27,00,25,00,31,00,27,00,22,00,\
      00,00
    

    I'm quite sure it is not needed, but I've seen it in a few scripts, and using it as an "additional safety measure" for people messing with their environment variables and/or registry. :)
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  8. adric

    adric MDL Addicted

    Jul 30, 2009
    958
    739
    30
    #8 adric, Dec 14, 2019
    Last edited: Dec 15, 2019
    (OP)
    I mentioned above that using a backtick before the special char solves the problem. $ALL is not a variable in my case, but an actual directory. I use special chars a lot with files and directories for sorting purposes
    Code:
    PS U:\> cd `$All
    PS U:\$All>
     
  9. adric

    adric MDL Addicted

    Jul 30, 2009
    958
    739
    30
    #9 adric, Dec 18, 2019
    Last edited: Dec 18, 2019
    (OP)
    On Win7 when I try to update an SSU mum file to make it removable, I get access to path is denied whereas on Win8.1, updating the .mum works without error. What's the best way to avoid this?
    Code:
    Exception calling "Save" with "1" argument(s): "Access to the path 'C:\Windows\
    servicing\Packages\Package_for_KB4523206~31bf3856ad364e35~amd64~~6.1.1.2.mum'
    is denied."
    At line:1 char:250
    + ... movable' }; $doc.save('C:\Windows\servicing\Packages\Package_for_KB45 ...
    +                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : DotNetMethodException
    
    Edit:
    Sorry, I got it working by prefixing the powershell command with nsudo -U:T