locked
Running a PS script against each servers logical drive(s) RRS feed

  • Question

  • Hi All,

    I'm trying to create a script to enumerate the logical disks of a list of servers and run a script against each drive, how is this done in powershell?

    E.G.

    $cim = new-cimsession -comp server1, server2, server3,server4
    Get-CimInstance -ClassName Win32_LogicalDisk -filter 'DriveType=3' -CimSession $cim  |
    Select PSComputerName, DeviceID | Invoke-Command -ComputerName PSComputerName -FilePath "C:\admin\RunScript.ps1" -ArgumentList DeviceID

    Thanks in advance.


    • Edited by DoJu Tuesday, November 26, 2019 12:22 AM
    Tuesday, November 26, 2019 12:04 AM

Answers

  • Hah - it's that old arglist bug with the fist element of an array. This will fix it:

    Get-CimInstance Win32_LogicalDisk -filter 'DriveType=3' -ComputerName server1 |
         ForEach-Object{
             Invoke-Command -ComputerName $_.PSComputerName -FilePath C:\admin\TelerikScan.ps1 -ArgumentList ($_.DeviceID+'\')
        }
    


    \_(ツ)_/

    • Marked as answer by DoJu Tuesday, November 26, 2019 6:15 AM
    • Unmarked as answer by DoJu Tuesday, November 26, 2019 6:16 AM
    • Marked as answer by DoJu Tuesday, November 26, 2019 6:17 AM
    Tuesday, November 26, 2019 5:57 AM

All replies

  • Before copying and guessing you need to learn basic PowerShell.  This is how to do this.

    Get-CimInstance Win32_LogicalDisk -filter 'DriveType=3' -ComputerName server1, server2, server3,server4 


    \_(ツ)_/

    Tuesday, November 26, 2019 12:26 AM
  • Thanks for the quick response, my 'copy/guess' code is what I already use to enumerate 100s of VMs with DriveType3 to obtain disk free space stats to CSV for reporting purposes.

    I'm simply trying to understand how to pass the 'selected' computername/DeviceID to an invoke command to run the script, I'll hopefully find the syntax and resolve myself.

    Thanks.





    • Edited by DoJu Tuesday, November 26, 2019 12:40 AM
    Tuesday, November 26, 2019 12:38 AM
  • Why pass it. Just add it to the script.

    If you would take the time to learn PS basics the answer would be obvious.  Why remotely gather informati9on then send it remotely?  It doesn't make any technical or logical sense.

    Also you can't pipeline objects into a remove session.  Basic PS would tell you this and tell you how to modify the script to include this information.

    All of your guesses are just wrong even if something similar works.  You are just lucky.

    Also your question is too vague to pose a better answer.  Rethink your issue and try to ask a question that tells what you want and not how you want to do it. 

    Also your invoke does nothing so why use it.  You already have all computer names  just pass them.

    Here is a best guess.  If it isn't what you want then you are going to have to ask a better question.

    Get-CimInstance Win32_LogicalDisk -filter 'DriveType=3' -ComputerName server1, server2, server3,server4 |
        ForEach-Object{
             Invoke-Command -ComputerName $_.PSComputerName -FilePath C:\admin\RunScript.ps1 -ArgumentList $_.DeviceID
        }

    Of course it would make more sense to alter the script to do everything.


    \_(ツ)_/

    Tuesday, November 26, 2019 12:52 AM
  • Hi JRV,

    These aren't 'guesses', the code shown is from the best in the powershell community (Jeff Hicks), all I've done is extended his code.

    https://www.petri.com/understanding-powershell-custom-properties-with-select-object-cmdlet

    My question wasn't vague: using a select list of computers (e.g. CIM objects), run a script against each logical drive(s) returned.



    • Edited by DoJu Tuesday, November 26, 2019 1:43 AM
    Tuesday, November 26, 2019 1:25 AM
  • That code has nothing to do with what you asked or the code you posted.

    Please take time to learn PowerShell and you will understand why I an suggesting that you learn. You will like it even more with some understanding of what PowerShell is.

    A also did not insult you.  I pointed out a mistake that you and many other non-technical users make when trying to use a new technology.   Formally trained techs always study the technology first.


    \_(ツ)_/


    • Edited by jrv Tuesday, November 26, 2019 1:59 AM
    Tuesday, November 26, 2019 1:57 AM
  • All working, thanks JRV for assistance.

    Get-CimInstance Win32_LogicalDisk -filter 'DriveType=3' -ComputerName server1 |
        ForEach-Object{
            $ADevice = $_.DeviceID+"\"
            $ADevice
            $state = Invoke-Command -ComputerName $_.PSComputerName -FilePath C:\admin\TelerikScan.ps1 -ArgumentList $ADevice
            $state
       }


    Vulnerable Telerik.Web.UI.dll identified at 'C:\Admin\Telerik.Web.UI.dll'. Version number '2015.1.401.45' matches version '2015.1.401' in Telewreck.
    Vulnerable Telerik.Web.UI.dll identified at 'C:\Admin\AdminTest\Telerik.Web.UI.dll'. Version number '2015.1.401.45' matches version '2015.1.401' in Telewreck

    Tuesday, November 26, 2019 4:16 AM
  • In programming we try to avoid unnecessary variable and steps. It serves no purpose, slows things dows, uses up memory and makes debugging harder.

    Get-CimInstance Win32_LogicalDisk -filter 'DriveType=3' -ComputerName server1 |
         ForEach-Object{
             Invoke-Command -ComputerName $_.PSComputerName -FilePath C:\admin\TelerikScan.ps1 -ArgumentList ($_.DeviceID+'\')
        }


    \_(ツ)_/


    • Edited by jrv Tuesday, November 26, 2019 5:58 AM
    Tuesday, November 26, 2019 4:28 AM
  • Tried that already:

    Invoke-Command : A positional parameter cannot be found that accepts argument '+\'

    Hence the need to append to variable, and have those variables return outputs for debug purposes to ensure the code is doing as it should.


    • Edited by DoJu Tuesday, November 26, 2019 5:00 AM
    Tuesday, November 26, 2019 4:34 AM
  • Sorry  but you copied it wrong.  That is not what I posted.


    \_(ツ)_/


    • Edited by jrv Tuesday, November 26, 2019 4:42 AM
    Tuesday, November 26, 2019 4:41 AM
  • I copied/pasted your exact code. You want to confirm by running in powershell ISE?

    Invoke-Command : A positional parameter cannot be found that accepts argument '+\'.
    At line:3 char:10
    +          Invoke-Command -ComputerName $_.PSComputerName -FilePath C:\ ...
    +          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidArgument: (:) [Invoke-Command], ParameterBindingException
        + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.InvokeCommandCommand

     My code works across multiple VMs etc

    Tuesday, November 26, 2019 4:51 AM
  • This is my exact code for that line:

       Invoke-Command -ComputerName $_.PSComputerName -FilePath C:\admin\TelerikScan.ps1 -ArgumentList $_.DeviceID+'\'

    Notice it looks nothing like the error message.

    This will show you how it works:

    Get-CimInstance Win32_LogicalDisk -filter 'DriveType=3' | ForEach-Object{$_.DeviceId+'\'}


    \_(ツ)_/

    Tuesday, November 26, 2019 5:50 AM
  • Hah - it's that old arglist bug with the fist element of an array. This will fix it:

    Get-CimInstance Win32_LogicalDisk -filter 'DriveType=3' -ComputerName server1 |
         ForEach-Object{
             Invoke-Command -ComputerName $_.PSComputerName -FilePath C:\admin\TelerikScan.ps1 -ArgumentList ($_.DeviceID+'\')
        }
    


    \_(ツ)_/

    • Marked as answer by DoJu Tuesday, November 26, 2019 6:15 AM
    • Unmarked as answer by DoJu Tuesday, November 26, 2019 6:16 AM
    • Marked as answer by DoJu Tuesday, November 26, 2019 6:17 AM
    Tuesday, November 26, 2019 5:57 AM
  • Thanks JRV, I'll use in my first PROD trache of VMs now debug is complete and code is returning correct results.
    Tuesday, November 26, 2019 6:17 AM
  • Your solution will be very slow and you should put the disk code in the PS1 file.

    Your approach is going to call every server as many times as there are disks.  This will place unneeded stress on the local and remote systems.  Consider fixing the script file to get the disk in the file.

    Learning basic PowerShell will help you to understand how this works and why we do specific design steps and patterns.

    Here is a free book which will teach you what PowerShell is and how to use it for management and automation.

    https://www.sapien.com/books_training/Windows-PowerShell-4

    The book is well reviewed and is available in paper from amazon.  This is a PDF of the book.

    This book is also a good reference for PS methods, CmdLets and subsystems.


    \_(ツ)_/

    Tuesday, November 26, 2019 6:29 AM
  • Thanks for the link JRV, greatly appreciated.

    Given time, I should be able to update the .ps1 script to run jobs in parallel across multiple servers at a time (e.g. weekend during off peak). The script will scan 100s of servers and 10s of millions of files to check for the vulnerability.

    Wednesday, November 27, 2019 3:07 AM
  • Read the start chapters (Learning Section). At the end there is a good chapter on Workflow. That is what you will need.


    \_(ツ)_/

    Wednesday, November 27, 2019 3:44 AM