Creating Hyper-V VMs with unique names using Powershell - powershell

I'm trying to make some sort of script that creates a new VM, only need it to be told to create a unique VM name (with some sort of logic, if possible, to check for existing names and using something different automatically or just telling me to use something else) . I understand a new VM is made using a unique GUID by default so there are no system conflicts, but I further need my script to go in and perform commands on the VM, such as starting the VMs, copying files onto it, etc. without a unique name I'm not sure how the script can automatically give commands to the right one.
For example, I have:
New-VM TestServer1 -AsJob -Generation 2 -MemoryStartupBytes 8192MB -NoVHD -SwitchName VSwitch-1
but if a VM named 'TestServer1' already exists, and I were to have my script automatically run:
Start-VM TestServer1
both VMs would turn on...
Edit:
Also, I know one can export the results of creating a new VM using 'Out-File' but I don't know what cleanest way to format the output to be read back later.

Related

Looking to delete a folder from explorer via registry

I am looking to delete highlighted value from registry shown in Picture, where 'standard user' is the user id from which system is logged in. I need power shell script so that I can deploy it in every machine of my organization from backend and this highlighted value gets deleted from every user's system profile.
Assuming you are planning on doing this via GPO I would advise two steps:
1- Create the script file and add it to the Files preference on your GPMC
2- Create a one-time Scheduled Task and run the remote script.
This code should do what you want as long as you adapt the Path to your needs. It will get a list of the Values inside the Key you point it to and match it using the where-object.
(Get-Item -Path HKCU:\SOFTWARE\Microsoft\OneDrive\Accounts\Business1\Tenants\Intune Test').Property | Where-Object{$_ -match 'Test Sync - Documents'} | Remove-Item
Deployment is up to you, please assume this code can be improved and or adapted. This is just the core block you need to achieve what you asked.

PowerShell to create a directory within a junction point; or within a volume with no drive letter?

I'm working with Hyper-V and clustering in a Server 2016 environment. This is something I'm new to, and I'm trying to utilize some of my PowerShell experience to script the creation of a new folder within a shortcut (junction point, specifically), OR within a volume label that does not reflect an associated drive letter.
Under the directory C:\ClusterStorage there are shortcuts/junction points for the following: Volume1, Volume2, Volume3. I want to create a new child directory called "Hyper-V", within the Volume1 junction point. However, when I try to run the below script, even though I'm designating C:\ClusterStorage\Volume1.lnk as the existing directory, and designating \Hyper-V as the new directory that I want to create as the subdirectory, the script tells me the Volume1.lnk already exists, as if it's trying to create the $rootpath anyway:
$rootpath = "C:\ClusterStorage\Volume1.lnk"
$newpath = "\Hyper-V"
New-Item -Path $rootpath -Value $newpath -ItemType Directory | Out-Null
So I'm not sure if there is a better approach to the above method I was trying (I cannot seem to find anything else). My other thought was to go directly to the source, if you will. Once the cluster is created properly, the Volume1 junction point actually points to a volume named Backups. This volume has a drive letter assigned within Disk Management initially, but for whatever technical reason, once the cluster is fully-configured properly the drive letter is no longer associated with the volume.
I do not want to create a new drive letter for the Backups volume, for fear that it will tamper with the cluster configuration, so I was wondering if perhaps there's a means of using PowerShell to create the Hyper-V subdirectory within the volume named Backups. I can only seem to find topics on "Add-PartitionAccessPath" when I search for a means of doing this, and Add-PartitionAccessPath seems to assign a drive letter, which I don't want to do as I mentioned.
Is what I'm trying to accomplish here possible? It seems using md hyper-v within C:\ClusterStorage\Volume1 (using CMD Prompt) works exactly as I want, if that helps. I'm just looking to do the same in PowerShell syntax. Thanks so much!

Can you use a powershell script to create a powershell script?

So this may be an odd request and maybe I'm going about this all wrong but I also have a unique situation. I have servers that are sometimes cloned and I need to run a script that I created on the clones servers. Due to the nature of the clones they cannot be connected to a network.
Currently I am manually putting the generic script on each server before cloning and then running the script on the clone server.
What I would like to do is have a script that runs and gathers all the information, say installed programs as an example, and generate a custom version of my current script on the servers before they are cloned.
I have both the powershell script that gets the server information and the generic one that makes the changes to the clone but I have not found a way to merge the two or any documentation so I don't know if i am hitting a limitation with this one.
Edit for more explanation and examples. I'm doing this from my phone atm so I dont have an example I can post.
Current I have a script that has a set number of applications to uninstall, registry keys to remove, services to stop ect. In another application I have a list of all the software that we have for each server and I can pull that data for each server. What I need to do is pull the data for each server, and have a script placed on each server that will uninstall just the programs for that server.
Currently the script has to run through every potential software and try to uninstall it and then check the other application to see if there are any additional programs that need to be uninstalled.
Hope this extra info helps.
Thanks.
Stop thinking of it as code.
Use script 1 to export blocks of text into a new file. for example, you might have a configuration that says all Dell servers must have this line of code run:
Set-DELL -attribute1 unmanaged
where on HP, the script would have been
Set-HP -attribute1 unmanaged
on web servers, you want:
set-web -active yes
where if not a web server, you want nothing.. so, your parent script code would look like:
$Dell = "Set-DELL -attribute1 unmanaged"
$HP = "Set-HP -attribute1 unmanaged"
$web = "set-web -active yes"
if (Get-servermake -eq "Dell")
{
$dell | out-file Child.ps1 -append
}
if (Get-servermake -eq "HP")
{
$HP | out-file Child.ps1 -append
}
if (Get-webserver -eq $true)
{
$web | out-file Child.ps1 -append
}
The result is a customized script for the specific server, child.ps1.
Now, you can take this and run with it. You could say add functionality to the child script like "Is it an AD controller", etc.
However, you might be better off having all of this in a single script, and just block off sections that don't apply in an if statement for example.
I'm still not totally sure I understand what your asking. If I've missed the mark, tell me how, and I'll tell you how to tweak this better. (And hopefully obvious is that the Get-whatever is sample code. I don't expect that to be what your using to determine a computer make/model/etc)

How to get an environment variable in a Powershell script when it is deployed by SCCM?

I've made a script to automatically change and/or create the default Outlook signature of all the employees in my company.
Technically, it gets the environment variable username where the script is deployed, access to the staff database to get some information regarding this user, then create the 3 different files for the signature by replacing values inside linked docx templates. Quite easy and logical.
After different tests, it is working correctly when you launch the script directly on a computer, either by using Powershell ISE, directly by the CMD or in Visual Studio. But when we tried to deploy it, like it will be, by using SCCM, it can't get any environment variable.
Do any of you have an idea about how to get environment variables in a script when it is deployed by SCCM ?
Here is what I've already tried :
$Name = [Environment]::UserName
$EnvVarUserName = Get-Item Env:\USERNAME
Even stuff like this :
$proc = gwmi win32_process -Filter "Name = 'explorer.exe'"
$report = #()
ForEach ($p in $proc)
{
$temp = "" | Select User
$temp.user = ($p.GetOwner()).User
$report += $temp
}
Thanks in advance and have a nice day y'all !
[EDIT]:
I've found a way of doing this, not the best one, but it works. I get the name of the machine, check the DB where when a laptop is connected to our network it stores the user id and the machine, then get the info in the staff DB.
I will still check for Matt's idea which is pretty interesting and, in a way, more accurate.
Thank you all !
How are you calling the environmental variable? $Env:computernamehas worked for me in scripts pushed out via SCCM before.
Why don't you enumerate the "%SystemDrive%\Users" folder, exclude certain built-in accounts, and handle them all in one batch?
To use the UserName environment variable the script would have to run as the logged-in user, which also implies that all of your users have at least read access to your staff database, which, at least in our environment, would be a big no-no.

Using Powershell to get a vm's own name

The short question is; can a VM use powershell to get its own name?
I have an environment where I have 12 identical sets of VMs. Each set has one jump server, and the naming convention is ##_APP_SET#, where ## is a corresponding NAT device, and SET# tells me the set of VMs.
On this APP VM, I have created a menu that uses an account on the external vCenter to turn the VMs in the set on and off. So from within the VM, it is connecting to its parent vCenter and running an action on another VM in the set. The problem is that I have the VM names hard coded in the script. For example, if I'm on 01_APP_SET1, I have a bunch of entries for 01_MACHINENAME_SET1, and on 02_APP_SET2, I have entries for 02_MACHINENAME_SET2, etc.
I am currently managing 12 different scripts on the 12 different APP VMs. I am hoping to make the script more general where the VM calls a get-vm on itself and parses out the preceding ## and trailing SET#, but not having much luck beyond getting a list of systems called APP with get-vm APP.
I'm thinking the best way to tackle this would be to give each APP VM a hostname matching its name in vCenter, then parsing out the information that way.
Is there any sort of identifiable information that is unique to the APP VM such as a external facing IP to be able to log in to outside of the private networking for the Set?
Perhaps something like this would be helpful:
$ip = (ipconfig | Select-String "IPv4 Address" | Select-String "192.168.1").Line.Replace("IPv4 Address. . . . . . . . . . . :","")
$vm = get-vm | ?{$_.Guest.IPAddress -like $ip}
Or group the VMs with tags in VC and use Invoke-VMScript to poke around other guests as necessary.