Tag: of

  • Get .Net Framework Version for the .DLL & .EXE files

    Get .Net Framework Version for the .DLL & .EXE files

    Working with many app/dev teams it is hard to find which version of Dot Net  an application was designed or made in.

    Now if your application server has multiple drives and depending on which drive the application resides it may be hard to find this information.

    Let’s assume there are two drives C: and D:.

    We will start with D: drive as it is easy.

    #Check DotNet Framework for .EXE & .DLL 
    #====================================#
    #====================================#
    
    #Files residing on any other drive except C: (OS Drive)
    #=====================================================#
    
    #Uncomment the line below to surpress any errors
    #$ErrorActionPreference = "SilentlyContinue"
    
    #Specifiy the filepath (I am using the root)
    $filepath=’D:\’
    
    #Get All files and filter .exe and .dll files
    $files=Get-ChildItem -Path $filepath -Recurse -include *.dll,*.exe
    
    #Loop through each file
    foreach($file in $files)
    {
        #Check the version of .NET for the file
        $version = [System.Reflection.Assembly]::ReflectionOnlyLoadFrom($file.FullName).ImageRuntimeVersion;
    
        #Write the Output on Screen + Capture to a file
        Write-Output "$file,$version" | Out-File D:\DotNetFiles_D.txt -Append
    
    }
    

    Now the C: drive is a little more work. The above method wont work because C:  drive has system files and depending on your rights you may not have access to them.

    You may get the following error:

    But there is a way we can get this accomplished. Good old dos commands to the rescue! We are basically going to get a list of .exe and .dll files from the C: drive and then run the above code against it.

    Lets capture the files:

    #For files residing on C: (OS Drive)
    #====================================#
    #Get a list of .exe files on the C: Drive and store to a file
    dir C:\*.exe /s /b | findstr /e .exe > C_Executable_Paths.txt
    
    #Get a list of .dll files on the C: Drive and store to a file
    dir C:\*.dll /s /b | findstr /e .dll > C_DLL_Paths.txt
    

    Now we have the .EXE files stored in C_EXE_Paths.txt and we query it for .NET versions and save the output to DotNetFiles_C_EXE.txt

    #Query each .EXE file capture in C_Executable_Paths.txt
    $files=Get-Content D:\C_Executable_Paths.txt
    
    #Looping through each file entry
    foreach($file in $files)
    
    {
    
        #Getting .NET version number for each file
        $version = [System.Reflection.Assembly]::ReflectionOnlyLoadFrom($file).ImageRuntimeVersion;
    
        #Writing output to an external file
        Write-Output "$file,$version" | Out-File D:\DotNetFiles_C_EXE.txt -Append
    
    }

    Similarly we have the .DLLfiles stored in C_DLL_Paths.txt and we query it for .NET versions and save the output to DotNetFiles_C_DLL.txt

    #Query each .DLL file capture in C_DLL_Paths.txt
    $files=Get-Content D:\C_DLL_Paths.txt
    
    #Looping through each file entry
    foreach($file in $files)
    
    {
    
        #Getting .NET version number for each file
        $version = [System.Reflection.Assembly]::ReflectionOnlyLoadFrom($file).ImageRuntimeVersion;
    
        #Writing output to an external file
        Write-Output "$file,$version" | Out-File D:\DotNetFiles_C_DLL.txt -Append
    
    }

    You might get errors for files that do not meet criteria or fails to list .Net version.

    This can be surpressed by using:

    $ErrorActionPreference = "SilentlyContinue"

    The output would be similar to:

    C:\Program Files\IBM\SQLLIB\BIN\db2dascmn.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2dascmn64.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2daskrb.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2daskrb64.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2daswrap.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2daswrap64.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2g11n.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2g11n64.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2genreg.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2genreg64.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2hrec.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2ica.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2ica64.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2install.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2install64.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2isys.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2jcct2.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2jdbc.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2jdbc64.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2kbc.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2kbc64.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2ldap.dll,v4.0.30319
    C:\Program Files\IBM\SQLLIB\BIN\db2ldap64.dll,v4.0.30319

    Now you can import this in Excel and go crazy!  😉

    Additionally, if you want to detect what version of .NETis installed on your server here is a cool utility (ASoft .NET Version Detector) to get you the info, as well as download links to the installer in case you need to download and install.

  • Connecting to a remote domain controller using PowerShell

    Connecting to a remote domain controller using PowerShell

    Covering one of the basic day to day task if you are a Windows Administrator; connecting to the domain controller.  I try to minimize logging onto servers as much as possible.  Your thought should be around connecting to the server remotely and doing the work as needed instead of natively logging on to it.

    I will be discussing two approaches below to connect to a domain controller:

    1. Connecting from a client machine on the same domain
    2. Connecting from a client machine on a different domain or a workstation/server

    Before we get started, and regardless of which approach you take below, the following will need to be installed on the client Windows machine. Primarily you need to get the Active Directory Module for Windows PowerShell installed.

    Installing the Active Directory Module

    GUI:

    The Active Directory for Windows PowerShell is already built-in into Windows Server operating systems (starting from Windows Server 2008 R2), but it is not enabled by default.

    On Windows Server 2016, you can install the AD for PowerShell module from the Server Manager (Add Roles and Features -> Features -> Remote Server Administration Tools -> Role Administration Tools -> AD DS and AD LDS Tools -> Active Directory module for Windows PowerShell).

    PowerShell:

    You can also install the module from the PowerShell console using the command:

    Install-WindowsFeature -Name "RSAT-AD-PowerShell" –IncludeAllSubFeature

    The RSAT-AD-PowerShell can be installed not only on the domain controllers, but also on any domain member server or even a workstation. The PowerShell Active Directory Module is installed automatically when you deploying the Active Directory Domain Services (AD DS) role (when promoting server to AD domain controller).

    Approach 1: Connecting from a client machine on the same domain

    First step you need to do is find all of your domain controllers and allow remote connections to it.

    Logon to your one of your domain controllers and open up PowerShell:

    winrm quickconfig

    [su_note note_color=”#fafae8″]You need to do this once on each domain controller so you can remotely connect to each one of them at a later time.[/su_note]

    You can read more about WinRM here.

    Alternatively, the following command can be ran in an elevated Powershell console on the DC. This enables WinRM and configures the firewall so that it can accept incoming commands.

    Enable-PSRemoting

    Once that is done you are ready to connect to your domain controller.

    Make sure your system is configured to run PowerShell scripts.

    #Set the ExecutionPolicy to allow execution of scripts
    Set-ExecutionPolicy Unrestricted

    Copy the content below and paste it into your PowerShell Editor. Rename your value of “yourdomaincontroller” to your actual DC Server name.

    #ConnectAD.ps1
    #Connect to your Domain Controller(DC)
    #Change the value after the -ComputerName to your know DC
    
    $session = New-PSSession -ComputerName "yourdomaincontroller" -Credential (Get-Credential)
    Invoke-Command $session -Scriptblock { Import-Module ActiveDirectory }
    Import-PSSession -Session $session -module ActiveDirectory

    Now all command you enter will be applied to the DC.

    To check if your connection is successful. Try the command below to get a list of all of your domain controllers.

    #Get a list of all domain controllers in your environment
    Get-ADDomainController -Filter * | Select-Object name

    Approach 2: Connecting from a client machine on a different domain or a workstation

    Windows Remoting works perfectly for same domain situations, and the set-up is relatively straight-forward. It’s extremely powerful when it works, and offers a highly flexible way to securely execute commands remotely.

    Problems arise however when trying to use WinRM in mixed domain environments, or where only one machine is on a domain. This requires some additional configuration steps outlined below.

    Logon to your one of your domain controllers and open up PowerShell and run the following:

    Enable-PSRemoting

    The following registry key needs to be added to the target domain controllers:

    New-ItemProperty -name LocalAccountTokenFilterPolicy -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -propertyType DWord -value 1

    Make sure the ports are open:

    By default, WS-Man and PowerShell remoting use port 5985 and 5986 for connections over HTTP and HTTPS, respectively.

    The module is interacting with AD through the Active Directory Web Service that must be installed on your domain controller (communication is performed over the TCP port 9389).

    [su_note note_color=”#f9f4ca” text_color=”#000000″ radius=”2″]In some environments, you may need to check if the server authentication certs are valid and not expired. Also, in some situations I have seen that if the client is not resolving the FQDN, it is because the DNSzone doesn’t exist in the source domain. Either the zone can be added, or the host file can be modified to add the DC’s FQDN. [/su_note]

    Trusted Hosts:

    Adding the client IP or name can help avoid errors.

    Depending on your environment and what is allowed or not one of the following should work for your situation.

    View the computers of TrustedHosts list

    To view the list of TrustedHosts added to the machine, type the following command. By default, its value is blank.

    Get-Item WSMan:\localhost\Client\TrustedHosts

    Add all computers to the TrustedHosts list

    Using the Set-Item cmdlet and the wildcard you can add all the computers to the TrustedHosts list with the following command.

    Set-Item WSMan:\localhost\Client\TrustedHosts -Value *

    Add all domain computers to the TrustedHosts list

    In the following command, replace .yourdomain.com with your own domain name.

    Set-Item WSMan:\localhost\Client\TrustedHosts *.yourdomain.com

    Add specific computers to the TrustedHosts list

    You can add specific computers you choose based on their hostname by separating them with a comma (,) using the following command.

    Set-Item WSMan:\localhost\Client\TrustedHosts -Value <ComputerName>,[<ComputerName>]

    Where ComputerName can be in the Server01 or Server01.yourdomain.com format

    Add a computer to an existing list of TrustedHosts

    If you have already added some computers to the TrustedHosts list and want to add an additional computer, without deleting the previous entries, you should use the following method. This is because the TrustedHosts list is updated based on the last Set-Item command you have run overwriting the previous entries.

    Use the following command to save the current TrustedHosts computer list to a curList variable.

    $currentList = (Get-Item WSMan:\localhost\Client\TrustedHosts).value

    To add a computer to the current list, type the following command by specifying both the variable you created and the computer name you are going to add.

    Set-Item WSMan:\localhost\Client\TrustedHosts -Value "$currentList , Server01"

    Alternatively, to avoid using a variable, add the -Concatenate switch to the Set-Item command to add both new and previous entries. For example:

    Set-Item WSMan:\localhost\Client\TrustedHosts -Concatenate -Value Server02

    Add computers to the TrustedHosts list using the IP address

    Similarly to the previous commands, you can use an IPv4 or IPv6 address. In the case of IPv6, you have to type the address between [].

    Set-Item WSMan:\localhost\Client\TrustedHosts -Value 10.10.10.1,[0:0:0:0:0:0:0:0]

    Add computers to the TrustedHosts list using multiple IP address (Most common)

    Set-Item WSMan:\localhost\Client\TrustedHosts -Value "10.10.10.1, 10.10.10.2"

    Another way to add trusted hosts is via an elevated Command Prompt:

    winrm set winrm/config/client @{TrustedHosts="10.0.2.33"}

    Importing the AD Module:

    Before using any cmdlets of the Active Directory module, you need to import it to your PowerShell session (on Windows Server 2012 R2/ Windows 8.1 and newer the module is imported automatically).

    Import-Module ActiveDirectory

    With this configuration, it’s now possible to authenticate and execute a command remotely with explicit credentials.

    Lets check if it is working:

    Enter-PSSession -ComputerName 10.0.2.33 -Credential $Credentials

    It WORKS! 🙂

    Common Errors & Solutions:

    Error: WinRM service started.  Set-WSManQuickConfig : <f:WSManFault…. WinRM firewall exception will not work since one of the network connection types on this machine is set to Public…… Change the network connection type to either Domain or Private and try again.

    Solution: 

    Enable-PSRemoting -SkipNetworkProfileCheck -Force

    Explanation:

    The above error message indicates that we have set the network to Public in order to enable PowerShell Remoting. Several ways exist to change the connection type. For some reason that only Microsoft knows, you can’t do this in the Network and Sharing Center.

     

    Error: Enter-PSSession : Connecting to remote server 10.0.2.33 failed with the following error message : The WinRM client cannot process the request….

    Solution:

    winrm set winrm/config/client @{TrustedHosts="10.0.2.33"}

    Explanation:

    In an Active Directory environment, you can just use the computer name to connect to a remote machine. If you remotely connect to a standalone machine, you usually have to use the IP address instead. If you try to connect to the remote computer with the Enter-PSSession cmdlet using the IP address of the remote machine, PowerShell will throw the above error.

    Error: Cannot connect to host…

    Solution:

    Check with your network/ firewall team if  the port 5985, 5986, and 9389 are open.

    Explanation: 

    Most of the times the ports are overlooked and are the root cause as to why the connection is not working

  • Delete Files and Folders Older Than X Days

    Delete Files and Folders Older Than X Days

    Often times admin have to creates tasks like removing log files or some other files on a regular schedule. Here is an automated way of removing files / folders older than X days.

    Create a Batch file or Powershell script and add it to scheduled task.

    [su_tooltip position=”north” content=”Here’s what all of those funky switches do. The first two arguments are for the InstallShield application, setup.exe. /S requests a silent installer, and /v lets the application know that you’re going to pass switches directly to the MSI. This is why the command structure after the /v is enclosed in double quotes. The /qn portion is MSI-speak for no user interface, while the REBOOT=R portion is toReallySupress the reboot. ADDLOCAL is describing what features to install locally, while REMOVE states to toss out the HGFS (Shared Folders) feature. This way ensures that new features will be added without having to call them all out in a list.”]Please check permissions on the files and folders. If you have unique or specialized permission on the file or folders these wont work.[/su_tooltip]

    Batch File:

    @echo off
    :: set folder path
    set dump_path=c:\shares\dump
    
    :: set min age of files and folders to delete
    set max_days=7
    
    :: remove files from %dump_path%
    forfiles -p %dump_path% -m *.* -d -%max_days% -c "cmd  /c del /q @path"
    
    :: remove sub directories from %dump_path%
    forfiles -p %dump_path% -d -%max_days% -c "cmd /c IF @isdir == TRUE rd /S /Q @path"

    Powershell:

    # set folder path
    $dump_path = "C:\shares\dump"
    
    # set min age of files
    $max_days = "-7"
     
    # get the current date
    $curr_date = Get-Date
    
    # determine how far back we go based on current date
    $del_date = $curr_date.AddDays($max_days)
    
    # delete the files
    Get-ChildItem $dump_path -Recurse | Where-Object { $_.LastWriteTime -lt $del_date } | Remove-Item

     

  • Bulk removal of Password Never Expires checkbox in AD

    No one intends this but it is a problem that sooner or later you will be come across in your system administrator career.

    I’ve see this resolved many different ways, but I like to narrow it down to a particular OU. Depending on your case you may want to clean this across the board in AD.

    Here is command prompt to the rescue:

    dsquery user "OU=Microsoft,DC=Redmond,DC=CORP,DC=LOCAL" -limit 4000 | dsmod user -pwdneverexpires no

    I haven’t tried this, but some have said the following works in Powershell:

    For OU:

    Get-ADUser -Filter {(ObjectClass -eq "user")} -SearchBase "OU=Offices,DC=Contoso,DC=com" | Set-ADUser -PasswordNeverExpires:$FALSE

    For AD:

    Get-ADUser -Filter {(ObjectClass -eq "user")} | Set-ADUser -PasswordNeverExpires:$FALSE