Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1279
  • Last Modified:

powershell function

Need a function that will determine if a passed value meets the following criteria:

if the string is exactly 6 characters long, and all numeric, then I would need the script to fail and report that the string was not in the correct format.

If the string is 7 characters long, then I need to validate that the last 6 characters are all numeric.  

If they are, it's assumed that this is a user ID and I need to pass that to another function to determine if that user's profile path and home directory are identical.  If they are, return false, if they are not, return true.

If those last 6 characters are not numeric, or if the length of the string differs from 7, then simply return false.
0
sirbounty
Asked:
sirbounty
  • 17
  • 11
  • 2
6 Solutions
 
Jamie McKillopIT ManagerCommented:
Hello,

This requires the free Quest cmdlets:

Function isNumeric ($x) {
	try {
		0 + $x | Out-Null
		return $true
	} catch {
		return $false
	}
}

Function verifypath ($Samaccount) {
	$user = Get-QADUser $Samaccount
	if ($user.profilepath -eq $user.homedirectory) {
		return $false
	} Else {
		return $true
	}
}

Function verifyuserID ($UserID) {
	$numcheck = isNumeric($UserID)
	if ($UserID.length -eq 6 -and $numcheck -eq $true) {
		Write-Host "String is not in correct format"
	}
	if ($UserID.length -eq 7) {
		$LastSix = $UserID.SubString(1,6)
		$numcheck = isNumeric($LastSix)
		If ($numcheck -eq $true) {
			verifypath($UserID)
		} Else {
			return $false
		}
	} Else {
		return $false
	}
}

Open in new window


JJ
0
 
LearnctxEngineerCommented:
Just use regular expressions to check if the username matches. As far as using the Quest Cmdlets. If you want to use Native MS tools without a third party install use the Active Directory cmdlets. I personally prefer to use native tools where I can :)

#requires -version 2
[CmdletBinding()]

param (
   [Parameter(Mandatory=$true)]
   [string[]]$username = $null
)
""
if (-not ($username))
{
   break
}

Import-Module ActiveDirectory

function Validate
{
   param (
      $InputData
   )
   if ($InputData -match "^[0-9]{6}$")
   {
      return "String is not in correct format"
   } elseif ($InputData -match "^[a-z][0-9]{6}$"){
      return $true
   } else {
      return $false
   }
}

function GetUser
{
   param (
      $InputData
   )
   try
   {
      $user = Get-ADUser -Identity $InputData -Properties ProfilePath, HomeDirectory
	  if ($user.homedirectory -eq $user.profilepath)
	  {
	     return $true
	  } else {
	  	return $false
	  }
   } catch {
      return "Invalid User"
   }
}

foreach ($user in $username)
{
   $tmp = Validate $user
   if ($tmp -eq $true)
   {
      $tmp = GetUser $user
      if ($tmp -eq $true)
      {
         "$($user): Directories match"
      } elseif ($tmp -eq $false){
         "$($user): Directories do not match"
      } else {
   	   $tmp
      }
   } elseif ($tmp -eq $false){
      "$($user): $($tmp)"
   } else {
      "$($user): $($tmp)"
   }
}

Open in new window

Usage is:

.\ScriptName -Username u111111, u222222, u333333
0
 
sirbountyAuthor Commented:
Yes, I like the quest cmdlets, but that wouldn't be an option for me - I need this to run without loading anything additional as it may be called on any particular device in our domain.

Ok, so there are a few questions I have on the 2nd script...

>>> [CmdletBinding()] - what's this line for?

>>> this section just ensures that a value is passed, i.e. mandatory that at least one parameter is supplied?
param (
   [Parameter(Mandatory=$true)]
   [string[]]$username = $null
)

>>> "" ---what's this for? : \


Finally, my purpose is really to only work against one user or group share at a time...what changes are needed to reduce to that?
0
Problems using Powershell and Active Directory?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

 
Jamie McKillopIT ManagerCommented:
Easy enough to change my script to not require the Quest cmdlets. You will need to have the AD Admin tools installed on any device this runs on though. there is no way around that.

Import-Module ActiveDirectory	
Function isNumeric ($x) {
	try {
		0 + $x | Out-Null
		return $true
	} catch {
		return $false
	}
}

Function verifypath ($Samaccount) {
	$user = Get-ADUser $Samaccount -Properties ProfilePath, HomeDirectory
	if ($user.profilepath -eq $user.homedirectory) {
		return $false
	} Else {
		return $true
	}
}

Function verifyuserID ($UserID) {
	$numcheck = isNumeric($UserID)
	if ($UserID.length -eq 6 -and $numcheck -eq $true) {
		Write-Host "String is not in correct format"
	}
	if ($UserID.length -eq 7) {
		$LastSix = $UserID.SubString(1,6)
		$numcheck = isNumeric($LastSix)
		If ($numcheck -eq $true) {
			verifypath($UserID)
		} Else {
			return $false
		}
	} Else {
		return $false
	}
}

Open in new window


This script would work on one user at a time by passing the variable to the verifyuserID function. You said you wanted a function. Do you actually want a whole script that prompts for the user ID input?

I'm not usre what you mean by "group share".

JJ
0
 
sirbountyAuthor Commented:
Also, I'm going to build a bit on this, so I don't need it to be a standalone function - I need it to be one I can just drop in my existing code...
0
 
Jamie McKillopIT ManagerCommented:
OK, as my script is written, you would just drop it in your existing code. You would then need your existing code to have the user ID in a variable and pass that variable to the function with the line:

verifyuserID($variable)

JJ
0
 
sirbountyAuthor Commented:
Tried it on my Win7 client, and two servers - one of them, which would be most of my environment, 2008SP2.  But I get an error:

The term 'Import-Module' is not recognized as a cmdlet, function, operable program,....

Is that a type-o on my part, or am I missing something else?
0
 
Jamie McKillopIT ManagerCommented:
You need to install the Active Directory Management Gateway on your DCs in order to use the Active Directory powershell module with non-R2 Windows 2008.

http://www.microsoft.com/en-us/download/details.aspx?id=2852

JJ
0
 
sirbountyAuthor Commented:
Sorry, most of the environment should be r2...I must have picked the wrong server.
I'll give it another shot elsewhere...
0
 
sirbountyAuthor Commented:
A little better, though the default context would require either a subtree search or a specify ldap path - it's not finding my user account as-is, since it is initiating the search from a child domain.

server account ldap://dc=abc,dc=def,dc=domain,dc=com
vs user account ldap://dc=def,dc=domain,dc=com
0
 
Jamie McKillopIT ManagerCommented:
You can add the -searchbase switch to specify where in AD you want to start searching.

$user = Get-ADUser $Samaccount -Properties ProfilePath, HomeDirectory -Searchbase "DC=def,DC=domain,DC=com"

JJ
0
 
sirbountyAuthor Commented:
Is there a way to simply read the current parent domain and search the subtree?
There may be a few instances where this will be used in a different domain altogether...
As for the current, it looks like the isnumeric function checks the full string - most likely there would be an alpha character preceeding the numerics, if it's a user ID.

Anyway to implement the regular expression from the other script?
0
 
sirbountyAuthor Commented:
Tried installing that update on a non-R2 server and it states it doesn't apply...any ideas?
Btw, increased the points here as I didn't expect it to be so involved.  Thanks
0
 
Jamie McKillopIT ManagerCommented:
The second time I'm passing the string to the isnumeric function, I'm only passing the last six characters.

I've modified the script to get the root domain.

You need to install that on a DC. Were you trying on a DC or a member server.

Import-Module ActiveDirectory	
Function isNumeric ($x) {
	try {
		0 + $x | Out-Null
		return $true
	} catch {
		return $false
	}
}

Function verifypath ($Samaccount) {
	$Root = [ADSI]"LDAP://RootDSE"
	$Domain = $Root.Get("rootDomainNamingContext")
	$Domain
	$user = Get-ADUser $Samaccount -SearchBase $Domain -Properties ProfilePath, HomeDirectory
	if ($user.profilepath -eq $user.homedirectory) {
		return $false
	} Else {
		return $true
	}
}

Function verifyuserID ($UserID) {
	$numcheck = isNumeric($UserID)
	if ($UserID.length -eq 6 -and $numcheck -eq $true) {
		Write-Host "String is not in correct format"
	}
	if ($UserID.length -eq 7) {
		$LastSix = $UserID.SubString(1,6)
		$numcheck = isNumeric($LastSix)
		If ($numcheck -eq $true) {
			verifypath($UserID)
		} Else {
			return $false
		}
	} Else {
		return $false
	}
}

Open in new window

0
 
sirbountyAuthor Commented:
Yeah, I copied the other function, and I think that worked.
Tried installing that on a DC in my test domain...it's 64-bit, but none of those options worked. : (
0
 
sirbountyAuthor Commented:
Missed one of your comments above, and I had modified the function slightly to return 'user' or 'group' based on that function's criteria.
How do I get that result in a variable or simply test it in an if condition?

If verifyUserID (P123456) doesn't seem to work for me...states the function isn't recognized...
0
 
sirbountyAuthor Commented:
A 'user' share is going to have those last 6 characters as numeric, with the first as an alpha.
A group share would most likely be anything else...
0
 
Jamie McKillopIT ManagerCommented:
Are your DCs Windows 2008 or Windows 2008 R2?

In your script, you could write a line of code to request the user input the the User ID:

$UserID = Read-host "Enter User ID"
verifyuserID($UserID)

JJ
0
 
Jamie McKillopIT ManagerCommented:
One other thing... you need to make sure the functions are at the top of your script, before the code that calls them.

JJ
0
 
sirbountyAuthor Commented:
I have both - W2k8 SP2 and W2k8 R2.

I'll try that - thanks.
0
 
sirbountyAuthor Commented:
The Get-ADUser seems to be failing...I get

Get-ADUser : A positional parameter cannot be found that accepts argument, followed by the user ID
0
 
Jamie McKillopIT ManagerCommented:
Just so we are on the same page here, what you are calling User ID is the SamAccountName, correct?

JJ
0
 
sirbountyAuthor Commented:
Correct
0
 
Jamie McKillopIT ManagerCommented:
Can you post a screen shot or cut and past the exact error?

JJ
0
 
sirbountyAuthor Commented:
Get-ADUser : A positional parameter cannot be found that accepts argument 'xxxxxxx'.
At E:\Batch\Test1.ps1:22 char:20
+     $user = Get-ADUser <<<<  $Samaccount -SearchBase $Domain -Properties ProfilePath, H
omeDirectory
    + CategoryInfo          : InvalidArgument: (:) [Get-ADUser], ParameterBindingExcepti
   on
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.ActiveDirectory.Mana
   gement.Commands.GetADUser

Open in new window

0
 
Jamie McKillopIT ManagerCommented:
Hmm, try putting -identity before $samaccount

JJ
0
 
sirbountyAuthor Commented:
Tried that, and even tried to mirror one of the examples in Get-ADUser, but I can't seem to get it to work...perhaps I should revisit the Quest idea... : \

Not sure why this isn't working....
0
 
LearnctxEngineerCommented:
">>> [CmdletBinding()] - what's this line for?"

It enables advanced function features such as being able to use [parameters()].

">>> this section just ensures that a value is passed, i.e. mandatory that at least one parameter is supplied?
param (
   [Parameter(Mandatory=$true)]
   [string[]]$username = $null
)

>>> "" ---what's this for? : \"

[Parameter(Mandatory=$true)] tells the script that a value must be provided for the parameter $username. So if someone ran the script without adding the -username parameter it will throw an error and not run.

"" is merely a carriage return. Short for Write-Host.

If you want to just run against a single user, then [string[]]$username = $null becomes [string]$username = $null. When casting a variable, adding [] means it will accept multiple values.

As for the positional parameter error.

"Get-ADUser : A positional parameter cannot be found that accepts argument 'xxxxxxx'.
At E:\Batch\Test1.ps1:22 char:20"

Change the searcher query as follows.
$user = Get-ADUser -Filter "Name -eq '$($Samaccount)'" -SearchBase $Domain -Properties ProfilePath, HomeDirectory

Open in new window

0
 
sirbountyAuthor Commented:
Thanks for the explanations.

That change gives this return:

Get-ADUser : The supplied distinguishedName must belong to one of the following partition
(s): 'CN=Configuration,DC=xxxxx,DC=com , CN=Schema,CN=Configuration,DC=xxxxx,DC=com , DC=
xxx,DC=xxxx,DC=xxxxx,DC=com'.
At E:\Batch\test1.ps1:22 char:27
+         $user = Get-ADUser <<<<  -Filter "Name -eq '$($Samaccount)'" -SearchBase $Domai
n -Properties ProfilePath, HomeDirectory
    + CategoryInfo          : InvalidArgument: (:) [Get-ADUser], ArgumentException
    + FullyQualifiedErrorId : The supplied distinguishedName must belong to one of the f
   ollowing partition(s): 'CN=Configuration,DC=xxxxx,DC=com , CN=Schema,CN=Configuratio
  n,DC=xxxxx,DC=com , DC=xxx,DC=xxxx,DC=xxxxx,DC=com'.,Microsoft.ActiveDirectory.Manag
 ement.Commands.GetADUser

It looks like the user domain is skipped based on those paths mentioned.
The first one is the parent, the last one is a grandchild (computer devices sit in that domain).  The child domain is where the user accounts reside...
Is there a way, rather than targeting the root, we can drop back a level from the existing?
i.e instead of dc=xxx,dc=xxxx,dc=xxxxx,dc=com, which is where the script would originate, could we start one level higher: dc=xxxx,dc=xxxxx,dc=com (without hard-coding it?).
0
 
sirbountyAuthor Commented:
Thanks gang - I'm actually abandoning this method as I've gotten something else working that I'm more famliar with.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 17
  • 11
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now