tirsdag den 2. januar 2018

AutoPilot a new W10 machine

When a brand new machine has been installed with Windows 10 and you want it to be enrolled in Store For Business and AutoPilot, you need to upload some properties, that can be tricky to find.

Fortunately we have the Powershell Superheroes and they have come up with a very easy powershell script for this - Get-WindowsAutoPilotInfo

But how do you get the info out of a brand new machine you just installed yourself?

1: Boot up the machine.
2: Press Shift+F10 as soon as the OOBE starts to open CMD
3: Type in the following commands in the shell:
4: Internet explorer opens and you can upload the CSV file created in line 4

I have not had any success adding a policy to the newly uploaded machine - unfortunately the browser crashes every time.

onsdag den 15. april 2015

Remove local userprofile from a machine remote

Apparently some people are looking for a way to remove local user profiles from computers remotely. Of course Powershell is the perfect tool for that. Here is an initial script for just that. Feel free to use and modify :-)

Function Remove-LocalProfile
{
<#
.SYNOPSIS
Removes a local userprofile from a computer
.DESCRIPTION
Removes a specific local userprofile from a computer. The profile can only be removed, if the user has not been locked on since last reboot.
.EXAMPLE
Remove-LocalProfile -Computer YourComputer -Samaccountname YourUser
Removes the local profile for YourUser on YourComputer
#>
[CmdletBinding()]
param
(
[parameter(Mandatory=$true,Position=0)]$Computer,
[parameter(Mandatory=$true,Position=1)]$SamAccountName
)
try
{
$Sid = Get-ADUser $SamAccountName | select -expand sid | select -expand value
}
Catch
{
Write-Warning "$SamAccountName not found in AD"
Break
}
if (Test-Connection $computer -Count 1 -Quiet)
{
$Profile = Get-WmiObject Win32_UserProfile -ComputerName $Computer | where {$_.SID -eq $Sid}
if ($Profile)
{
Try
{
Write-Verbose "Removing $SamAccountName from $Computer"
$Profile.delete()
}
catch
{
Write-Warning "The Profile of $SamAccountName is locked. Please restart $Computer and try again."
}
}
else
{
Write-Warning "$SamAccountName not found on $Computer"
}
}
else {Write-Warning "$Computer is not online"}
}

mandag den 30. december 2013

Give non-administrators access to PSRemoting

It is quite simple, but very non-powershellish, to frant non-administrators access to use remote sessions on a remote server.

You need to log on to the server (the non-powershellish part) open Powershell with Administrator prevelidges and run this command:
Set-PSSessionConfiguration -Name Microsoft.PowerShell -showSecurityDescriptorUI

Press Y and Enter and a nice little GUI-box opens, where you can adjust the ACL accordingly.

If you need your non-administrators to run the x86 version of Powershell, use this command instead:

Set-PSSessionConfiguration -Name Microsoft.PowerShell32 -showSecurityDescriptorUI

tirsdag den 11. juni 2013

The type initializer for 'Microsoft.Exchange.Diagnostics.ExTraceConfiguration' threw an exception.

I am currently working on a migration project. My company is migrating from Lotus Notes to Microsoft Exchange/Office 365.

We are currently in a POC where all Notes mailusers have have been created in AD as Contacts. My task is to convert the Contact objects to mailenabled AD users.

Since the mechanism for converting Notes users to Contacts is pretty messy and unreliable, I use my favorite tool (Powershell, if you should wonder) to retrieve the correct information directly from Notes. I use a variant of a custom cmdlet described earlier in my blog.

I need a live connection to the Exchange server to Mail-enable the AD users once they have the correct proxyaddresses and targetaddress. The AD stuff is done by importing the activedirectory module.

Everything worked fine in development, but once combined to a final script, the console became strangely buggy after running the script. Ordianry stuf like ping gave no results, and the get-help cmdlet stopped working.

I could live with that, since the script should run scheduled and the console would be closed after each run.

The I upgraded to Powershell 3.0.

In Powershell 3.0 the script no longer stuck to making the console buggy. In stead Powershell crashed with this dialog box:

and this console output:
The type initializer for 'Microsoft.Exchange.Diagnostics.ExTraceConfiguration' threw an exception.
    + CategoryInfo          : OperationStopped: (MyExchangeServer.MyDomain.dk:String) [], PSRemotingTransportException
    + FullyQualifiedErrorId : JobFailure
    + PSComputerName        : MyExchangeServer.MyDomain.dk


The funny thing was, that the script continued and did, what it was supposed to do, until the "Close program" button was pressed.

I could have lived with that, but unfortunately the Task Scheduler is polite and presses the "Close program" button as soon as it sees it, so I had to figure out, what causes the problem.

Several hours of bug tracking later, it turns out to the order in which the cmdlets loaded are used - or so I thought.

The original setup, that causes the error is like this:
. 'C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1'
Connect-ExchangeServer -auto
Get-ADUser <Samaccountname>
Get-MailUser <Samaccountname>

To make it work without failing I added this:
. 'C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1'
Connect-ExchangeServer -auto
Get-Mailuser StupidExchangeBug
Get-ADUser <Samaccountname>
Get-MailUser <Samaccountname>

And gone was the error!

Just to get rid of the nasty red when running Get-Mailuser StupidExchangeBug, which does not look nice in the transcript file, I added -ErrorAction silentlycontinue, and rescheduled the task.

This morning at the office i looked at my task and was quite surprised to see, that the task had failed. I ran the script in the console and the annoying messagebox popped up again - script still running and doing its thing. DANG!

This time the bug tracking was cut down to removing the erroraction switch and the error disappeared again.

Please feel free to test this yourself by running the above described commands. The shell crashes, if you are on PS 3.0 so please run "Powershell -noprofile" before entering the code, unless you don't care about your console ;-)

tirsdag den 4. oktober 2011

Get-SQLData


I like working with FIM (Microsoft ForeFront Identity Management). I'm currently working with Søren Granfeldt on a Homedir MA, and i find myself needing som extra entries from the metaverse in my Powershell script. I designed this cmdlet to get me, what i needed:

Function Get-SQLData {
<#
.SYNOPSIS
   Gets data from MSSQL tables

.DESCRIPTION
   Gets data from MSSQL tables
 
.EXAMPLE
    Get-SQLData -SQLServer FLHSRV144 -SQLDBName FIMSynchronizationService -Schema dbo -Select * -Field Uid -Value ITSABA
 Returns the entire record containing ITSABA on the field Uid in the FIMSynchronizationService database on FLHSRV144
.EXAMPLE
 Get-SQLData -SQLServer FLHSRV144 -SQLDBName FIMSynchronizationService -Schema dbo -Select isMailUser -Field Uid -Value ITSABA
 Returns the value for isMailUser for the record where Uid equals ITSABA in the FIMSynchronizationService database on FLHSRV144
#>
Param ($SQLServer = "FLHSRV144",
 $SQLDBName = "FIMSynchronizationService",
 $Schema = "dbo",
 $Table = "mms_metaverse",
 $Select = "*",
 $Field = "Uid",
 $Value
 )
 $SqlQuery = "SELECT $Select FROM [$SQLDBName].[$Schema].[$Table] Where $Field = '" + $Value + "'"
 $SqlConnection = New-Object System.Data.SqlClient.SqlConnection
 $SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True"
 $SqlConnection.open()
 $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
 $SqlCmd.CommandText = $SqlQuery
 $SqlCmd.Connection = $SqlConnection

 $Reader =  $SqlCmd.ExecuteReader()
 $Counter = $Reader.FieldCount
 $info = @{}
 while ($Reader.Read()) {
 for ($i = 0; $i -lt $Counter; $i++) {
 $info.add($Reader.GetName($i),$Reader.GetValue($i))
 }
 }
 $Reader.Close()
 $SqlConnection.Close()
 New-Object PSObject -Property $info
    }

Now all MV-entries are accessible from my script.
Feel free to reuse and modify.

Lotus Notes Shelling


I hate Lotus Notes - and I love Powershell. Now i have a solution:

I found an old manual on Google explaining how to access Notes via Powershell. Since it was a cashed site it I updated the manual and posted it here, so it may benefit all other Shellers.

My system:
Windows 7
Notes 8.5
Powershell 2.0


Make sure that the path of your notes id file is correct.
Check your notes.ini file : KeyFilename=the direcory containing the id file\yourID.id

[Generate the Domino.dll file]
You need a tlbimp.exe file.
I copied C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\tlbimp.exe to my local machine (C:\Temp) from a CS installation on a different machine. I think any installed version of VS could do.
Run the following commands:
regsvr32 "C:\Program Files\Lotus\Notes\nlsxbe.dll"
C:\Temp\tlbimp.exe "C:\Program Files\Lotus\Notes\domobj.tlb"

then you can see that the the Domino.dll is generated in the same directory:
C:\Temp\Domino.dll

Basic shell:

#[Connect to the DB, Get View and Get the Doc]
#including the Domino.dll
add-pssnapin "C:\Temp\Domino.dll"

#Specifying the Password (the password matching your notes.id file)
$NotesPassword = "PASSWORD"

#Specifying the Server Name
$NotesHost = "SERVER_NAME";

#Specifying the DB Name
$Database = "DB_NAME.nsf";

#Create Session
$Session = New-Object Domino.NotesSession

#Initialize the Session
$Session.Initialize($NotesPassword);

#Get the DB
$db = $Session.GetDatabase($NotesHost, $Database)

The rest is up to you ;-)