List of Hyper-V Servers Remotely into CSV Format? - powershell

Im thinking this would be easy, but want to make sure it's possible.
Is there an easy way to grab a list of all Hyper-V Servers/VM's on a machine and maybe export it to a CSV File? (excel spreadsheet).
Get-VM returns quite a bit of information, but is there any way to split that? Maybe store them into an array?
This is my first time with powershell so Im mainly wanting to make sure this is a easily doable task.
Problem is.....the machine is a Windows 2008 Server R2 that doesn't support Hyper-V Modules I believe (I think only Win 8 does).....so I've been remoting into it....so can I use Powershell to Remote into it and Run this script?
I tried doing a Get-VM from command line using Invoke-Command, but it complains about File-Path....but I was just trying to do a Get-VM from command line.

Sounds to me like you need to take some smaller steps first. In this case, I would avoid PowerShell remoting. If you have the modules installed and and loaded in your PowerShell session you should be able to point to a remote host to run Get-VM without having to do anything crazy.
As for filtering output for a CSV, You should use Select (to select certain properties of the object and ignore others) and Where-Object (to filter what objects are displayed, based on properties of the object.
Get-VM -ComputerName HyperVHost.constoso.local | Where-Object {$_.OS -match "2008"} | Select Name, Host | ExportTo-CSV C:\csv.csv
The above example was fictional, but it's the syntax I would use to filter input before putting it into a CSV. Again, it sounds like you're going to need a more basic understanding of how to work with the pipeline, understand what options you have to work with objects, etc.

Related

cmdlets on computers exported from AD

I've written a Powershell script to automate a process we have been doing manually, but for some reason it does not work when using a .csv of machines exported from AD. If I query AD for machines with a certain property, output the results to a .csv which are then read into an array and subsequently run any cmdlet on the machines in the array, the cmdlet doesn't fail but always returns a negative result. For instance, if I run test-connection -ComputerName $computer on a computer manually, against a manually created array or an array created from a manually created .csv it returns the proper results. However, if I run the same command against a .csv created from running the Get-ADComputer cmdlet, all machines return false even if they're up and running. Any ideas on what would cause this?
Thanks for the responses. I was actually able to get assistance elsewhere and get it figured out. Due to hostname length variations, Get-ADComputer was adding trailing spaces so they were all the same length. This wasn't visible in .csv . After removing the trailing spaces from each hostname it worked normally.

Write to Profile File After Installing PowerShell Module with PowerShellGet

I have a custom PowerShell module with two cmdlets. I have it successfully, but manually, deployed on my machine. However, I deployed it by placing the binary file and module manifest in a location, and then registering the module. I also had to manually write an Import-Module command into my 'all users' profile.
Now I am sure I can deploy this module with Publish-Module, but how do I get the Install-Module to write the Import-Module statement to the profile file?
As of PowerShell 3.0, a module is automatically imported when a command from the module is invoked. This was a brilliant on Microsoft's part; however, it did require that modules are located in a location where PowerShell looks for modules by default. Makes sense. You can see those locations by running the following command:
$env:PSModulePath -split ';'
Is there a reason you'd rather not use one of the paths stored in the above environmental variable? That said, I'd keep your code out of the "C:\Windows\System32..." path. The other options are better: "C:\Program Files\PowerShell\Modules" (AllUsers) and "C:\Users\tommymaynard\Documents\PowerShell\Modules" (CurrentUser). Depending on your PowerShell version/OS, those path could be different. You won't need to write an Import-Module command into a $PROFILE script if you get the module into a preferred location. Maybe you already know this, but maybe not.
You're not going to get Install-Module to write to any of the $PROFILE scripts.
$PROFILE | Select-Object -Property *
Well, not by default anyway. You could write your own Install-Module function, that runs PowerShellGet's Install-Module function, and includes writing to various $PROFILE scripts. The problem is that you'll need to include logic so you don't blow away the contents of someone's $PROFILE script if it's not empty, and only append to it.
Seriously though, this is turning into a lot of work, when you could drop the module into a location where PowerShell can find it on its own.
Edit: It just occurred to me, you can add a value/path to the $env:PSModulePath environmental variable. It's a single string with semi-colon delimiters:
$env:PSModulePath.GetType().Name
Therefore, it'd look like this:
$env:PSModulePath += ';C:\Another\Path'
That's great and all, but again how might you stage this, right? It takes you back to the write-to-all-the-$PROFILE-scripts problem,... although you may be able to update the variable via Group Policy Preferences. Again, probably better to just relocate your module.

Get-ChildItem File Sorting

I have a script that I run at my work that uses get-childitem to get all the files of a certain type in a storage drive and sorts and moves them to an archive drive. I'd like to automate this process to run once everyday but I realized I would have a problem in doing so.
Occasionally, when this script is run a file or two will still be in the process of transferring over to our storage drive. If I let the script move this file while it is still being transferred from our customer, it gets corrupted and won't open later.
I know how to filter based on file type and date and other basic parameters, but I'm not entirely sure how I tell this script to exclude files that are currently growing in size.
Below is what I'm currently using to filter what I want to move:
$TargetType = "*.SomeFileType"
$TargetDrive = "\\Some\UNC\Path"
Get-ChildItem $targetdrive\$targettype | ForEach-Object {$_.fullname} | Sort-Object | out-file $outStorageMove
Also, at the moment I'm putting everything that get-childitem finds into a text file, that gets invoked later so that I can manually edit what I want it to move. I'd like to get rid of this step if at all possible.
So, move is essentially copy and delete.
So, like gvee state, Copy-Item is a better option, to get you past your stated concern, monitor for the copy to complete. My addition would be to delete once the copy is done and you have verified the copy.
Or use Bits as a job to do this.
Using Windows PowerShell to Create BITS Transfer Jobs
https://msdn.microsoft.com/en-us/library/windows/desktop/ee663885(v=vs.85).aspx
You can use PowerShell cmdlets to create synchronous and asynchronous Background Intelligent Transfer Service (BITS) transfer jobs.
All of the examples in this topic use the Start-BitsTransfer cmdlet. To use the cmdlet, be sure to import the module first. To install the module, run the following command: Import-Module BitsTransfer. For more information, type Get-Help Start-BitsTransfer at the PowerShell prompt.

Is it possible to delete or overwrite cmdlets?

I'm working with DNS resource records in Powershell 5 using code that I inherited from the guy who was trying to do this before me. The cmdlet I am trying to use is Add-DnsServerResourceRecordA.
Part of his code has import-module certain folder\PowerShell\Modules\DnsServer. The weird thing is, it seems like as I was trying bits and pieces of the code earlier, I was able to use the add-DNSblah cmdlet. Now, after It ried running the whole script including the import-module, Powershell is saying that the cmdlet does not exist natively, and when I import the module and run it it is giving me Add-DnsServerResourceRecordA: Invalid Class.
It is my understanding that Add-DnsServerResourceRecordA should be included in my normal Powershell 5.0. Could that Import-Module have permanently damaged PS somehow? Why else would the cmdlet not show up, even in a Get-Command "dns"?
I'm pretty sure you will need the Remote Server Administration Tools (RSAT) installed to have these cmdlets available on a non-server Windows OS.
You can download them from this page: https://www.microsoft.com/en-gb/download/details.aspx?id=45520.
Not really sure why the Import-Module does not fail if the DNSServer module is not present on the system.
If RSAT are already installed, you can try to reinstall them.

Is it possible to/how do you stop powershell using certain cmdlets?

Powershell is clearly a lot better than cmd but it hides basic functionality. I normally use it to figure out how to use commands that I want in scripts but it breaks a large number of basic things and I end up using both side by side if I hit a sticky spot.
Today this was removing a directory - rd or rmdir - both of which are broken in powershell in favour of one it's undocumented (from the commandline) cmdlets Remove-Item. I seem to run into it all the time though - sc (for mucking around with services); where for finding what program is being called when you type a command etc etc.
Hilariously I actually got the problem with sc and then googled to find out the command where only to discover that didnt work in powershell either! That was a confusing day
In some cases once you know this is what's going on you can type the full exe name (for instance 'where.exe' will work whereas 'where' on its own wont).
This isn't the case with rmdir however. Although interestingly typing 'where rmdir' in cmd doesnt work.
So... my question is this - Is there a way of turning off (preferably all) cmdlets in powershell and just getting the normal stuff instead?
There is no need to turn off cmdlets in powershell as that would destroy the very reason for having it.
Most of the "normal" stuff is there anyway, which you can find by using the get-alias command.
C:\> get-alias
CommandType Name
----------- ----
Alias % -> ForEach-Object
Alias ? -> Where-Object
Alias ?? -> Invoke-NullCoalescing
Alias ac -> Add-Content
Alias asnp -> Add-PSSnapin
Alias cat -> Get-Content
Alias cd -> Set-Location
Alias chdir -> Set-Location
.....
..... AND A WHOLE LOT MORE!
If you are missing a command that you really, really want to have, then you can easily add a new alias:
Set-Alias python2 "C:\Python27\python.exe"
In order to avoid having to do this every single time, you can simply add this into your startup profile. Just type in $PROFILE into the command prompt and it will show you the file path. If it doesn't exist, simply create it, and any powershell commands you add to the top will be automatically invoked when you start a new session.
And last thing. All of the commands are documented, and you can get to them easily using just two.
Just type this into your command prompt and you will be on your way to Powershell enlightenment!
get-help get-command
get-command -noun Item
get-command -verb get
I just realised the answer to my question was buried in the comments to the other answer:
To remove a cmdlet in powershell you run
Remove-Item alias:something.
I can confirm you can do this by using the profile mentioned in Josh's post, however there are a couple more steps:
By default you cant run scripts in powershell. You have to change this using set-ExecutionPolicy.
I changed this by using an admin powershell and typing
set-executionpolicy bypass
This will let you run any script you like
Then in my profile script I have lines like:
Remove-Item -force alias:sc
You wont see errors from this script when it runs and it wont do anything unless you have force.