Read key file located in C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys - c#

One of utility we created generates too many files in C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys. To safely delete these files I want to open each file and exam the key. How can I open these key files in C#? I looked at code at here. The code only returns public key. Can I get more information form these key files?

I ended up using following powershell to get a list of valid key from certificate store. I also added c2319c42033a5ca7f44e731bfd3fa2b5 to the list since I am using IIS service. I delete any key file not in this list.
$MachineCertStores = Get-ChildItem Cert:\LocalMachine
$UserCertStores = Get-ChildItem Cert:\CurrentUser
Foreach ($Store in $MachineCertStores)
{
$path = "Cert:\LocalMachine\" + $($store.Name)
$keys = Get-ChildItem $path
Foreach ($Key in $Keys)
{
$UniqueKeyName = $key.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
if ([string]::IsNullOrWhitespace($UniqueKeyName)){
}else{
write-host $UniqueKeyName
$file = Get-Content "validkey.txt"
$containsWord = $file | %{$_ -match $UniqueKeyName.substring(0,32)}
If($containsWord -contains $true)
{
}else{
$UniqueKeyName.substring(0,32) | Out-File 'validkey.txt' -Append
}
}
}
}
Foreach ($Store in $UserCertStores)
{
$path = "Cert:\CurrentUser\" + $($store.Name)
$keys = Get-ChildItem $path
Foreach ($Key in $Keys)
{
$UniqueKeyName = $key.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
if ([string]::IsNullOrWhitespace($UniqueKeyName)){
}else{
write-host $UniqueKeyName
$file = Get-Content "validkey.txt"
$containsWord = $file | %{$_ -match $UniqueKeyName.substring(0,32)}
If($containsWord -contains $true)
{
}else{
$UniqueKeyName.substring(0,32) | Out-File 'validkey.txt' -Append
}
}
}
}

Related

How to retrieve all AD object using the USNChanged property and HighestCommittedUsn C#

I'm trying to do some kind of AD sync using USNChanged and retrieve all of the objects using the USNChanged property, but the entire process sounds a bit cryptic to me.
I have a PowerShell code that basically does what I need, but I was wondering you if anyone can help me convert it into a C# code. I would appreciate the help.
PS Code:
$highestCommittedUSN = (Get-ADRootDSE -server $preferredDC -properties * | select-object -property highestCommittedUSN).highestCommittedUSN
$lowUSN = 0
$highUSN = 0
for ($i=1000; $i -le $highestCommittedUSN ; $i=$i+10000 ) {
[system.gc]::Collect()
$error.clear()
$highUSN=$i
write-host "(&(usnChanged>=$lowUSN)(usnChanged<$highUSN))"
$adObjects = (Get-ADObject -LDAPFilter "(&(usnChanged>=$lowUSN)(usnChanged<=$highUSN))" -Server $preferredDC -Properties * -IncludeDeletedObjects)
($adObjects).count
if ($error.count -lt 0) {
for ($j=$lowUSN; $j -le 490767138; $j=$j+1 ) {
">>> " + $j
$adObjects = Get-ADObject -LDAPFilter "(usnChanged=$j)" -Server "DCName" -Properties * -IncludeDeletedObjects
$adObjects | ConvertTo-Json | Out-File -FilePath ff.json -Append
if ($error.count -ge 1) {
"There is problem with this USN " + $j + " on " + $preferredDC | Out-File -FilePath badUSN.txt -Append
$adObjects.distinguishedName
}
$adObjects.distinguishedName
}
}
$lowUSN=$highUSN
$adObjects.distinguishedName
$adObjects = $null
$error.clear()
}
I did found a similar question here : How to read "uSNChanged" property using C# , but I'm not sure if I can use that answer.

Powershell Balloon Notification Vanishes before showing

Have another head scratcher here, simply put my balloon notification does not work when fired from inside of a function that is inside of a job, the icon shows up for a fraction of a second and then disappears, tried several compinations of -wait -sleep -sleep-start to see if i could delay its "completion" since i feel the function is not running it's full course before ending, it works outside of the job/function, but inside it does not, here is the snippet I am calling
function MakeToolTip
{
[CmdletBinding(SupportsShouldProcess = $true)]
param
(
[Parameter(Mandatory=$true)]
$Text,
[Parameter(Mandatory=$true)]
$Title,
[ValidateSet(‘None’, ‘Info’, ‘Warning’, ‘Error’)]
$Icon = ‘Info’, $Timeout = 10000
)
Add-Type -AssemblyName System.Windows.Forms
if ($script:balloon -eq $null)
{
$script:balloon = New-Object System.Windows.Forms.NotifyIcon
}
$path = Get-Process -id $pid | Select-Object -ExpandProperty Path
$balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path)
$balloon.BalloonTipIcon = $Icon
$balloon.BalloonTipText = $Text
$balloon.BalloonTipTitle = $Title
$balloon.Visible = $true
$balloon.ShowBalloonTip($Timeout)
}
This is called with: MakeToolTip "Testing" "VNC Connections" Info
The full code of the script is here, lines 239-269: https://pastebin.com/7Q4gwLJe
I'm considering running the balloon in a separate job? Maybe the pipeline is completing it too quickly because there too much other stuff going on?
EDIT
Finding that when wrapped in a job a balloon notification does not work, very strange behavior
$MakeToolTip =
{
function Makeit {
[CmdletBinding(SupportsShouldProcess = $true)]
param
(
[Parameter(Mandatory=$true)]
$Text,
[Parameter(Mandatory=$true)]
$Title,
[ValidateSet(‘None’, ‘Info’, ‘Warning’, ‘Error’)]
$Icon = ‘Info’, $Timeout = 10000
)
Add-Type -AssemblyName System.Windows.Forms
if ($balloon -eq $null)
{
$balloon = New-Object System.Windows.Forms.NotifyIcon
}
$path = Get-Process -id $pid | Select-Object -ExpandProperty Path
$balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path)
$balloon.BalloonTipIcon = $Icon
$balloon.BalloonTipText = $Text
$balloon.BalloonTipTitle = $Title
$balloon.Visible = $true
$balloon.ShowBalloonTip($Timeout)
write-host $Text, $Title
}
}
$balloonjob = Start-Job -ScriptBlock {MakeIt 'Hi' 'There'} -InitializationScript $MakeToolTip -Name "BalloonJob"
Register-ObjectEvent $balloonjob -EventName StateChanged -Action {
if ($eventArgs.JobStateInfo.State -eq [System.Management.Automation.JobState]::Failed)
{
Write-Host "Closing the Balloon"
# This command removes the original job
$sender | Remove-Job -Force
# These commands remove the event registration
$eventSubscriber | Unregister-Event -Force
$eventSubscriber.Action | Remove-Job -Force
}
}

Why is Get-ChildItem command not reading C Drive from C# Program?

$archive = ("*www*","*Backup*","*inetpub*","*wwwroot*","*archive*","*Archive*","*ARCHIVE*","*WINDOWS*","*Program Files*","*JioMediaShare*","*thumbnails*");
function Log-Message {
[CmdletBinding()]
Param (
[Parameter(Mandatory=$true, Position=0)]
[string]$LogMessage
)
Write-Output ("{0} - {1}" -f (Get-Date), $LogMessage)
}
function Exclude-Directories {
Process {
$allowThrough = $true
foreach ($directoryToExclude in $archive) {
$directoryText = "*\" + $directoryToExclude
$childText = "*\" + $directoryToExclude + "\*"
if (($_.FullName -like $directoryText -and $_.PsIsContainer) -or $_.FullName -like $childText) {
$allowThrough = $false
break
}
}
if ($allowThrough) {
return $_
}
}
}
Log-Message "Starting Search"
Get-WMIObject Win32_LogicalDisk | ForEach-Object {
Log-Message $_.DeviceID
Get-ChildItem -Path $_.DeviceID -Include *.jpg, *.png, *.bmp, *.jpeg, *.gif, *.webp -Recurse |
Exclude-Directories |
where {!$_.PSIsContainer} |
Select-Object FullName, Name, BaseName, CreationTime, LastWriteTime, Length |
Export-Csv -NoTypeInformation -Path Images.csv -Encoding UTF8 -Append |
% {$_.Replace('"','')}
}
Log-Message "Search completed."
If I run the above script independently, that script is running without errors and search Images in C:, : and E: drive.
string text = System.IO.File.ReadAllText(#"New-Item.ps1");
using (PowerShell PowerShellInstance = PowerShell.Create()) {
// use "AddScript" to add the contents of a script file to the end of the execution pipeline.
// use "AddCommand" to add individual commands/cmdlets to the end of the execution pipeline.
PowerShellInstance.AddScript(text);
Collection<PSObject> PSOutput = PowerShellInstance.Invoke();
foreach (PSObject outputItem in PSOutput) {
// if null object was dumped to the pipeline during the script then a null
if (outputItem != null) {
Console.WriteLine(outputItem.BaseObject.ToString() + "\n");
}
}
if (PowerShellInstance.Streams.Error.Count > 0) {
Console.Write("Error");
}
Console.ReadKey();
}
When running the PowerShell script in a C# program, it is skipping search in the C: drive.
I think the issue is with -Path $_.DeviceID. As $_.DeviceID is not a full path, but just something like 'C:', PowerShell is trying to interpret what you mean and I think it is defaulting to the working directory for that drive (e.g. the value of $pwd).
One option to get around this is to run Set-Location "$($_.DeviceID)\" before the enumeration and drop the -Path parameter from the call to Get-ChildItem. That is:
Set-Location "$($_.DeviceID)\"
Get-ChildItem -Include *.jpg, *.png, *.bmp, *.jpeg, *.gif, *.webp -Recurse ...

search file in specific child folder in powershell

As per requirement, search file in specific child folder and then copy to destination path. I had implemented in c#.NET earlier but now want to convert in PowerShell.
foreach (var directory in Directory.EnumerateDirectories(sourcePath, specificChildFolder, SearchOption.AllDirectories))
{
var pathSrc = Path.Combine(directory, "xyz.config");
if (File.Exists(pathSrc))
{
File.Copy(pathSrc, pathDst, true);
break;
}
}
Here is code which you can use:
$path = "C:\Users\user1\Desktop\Config Rework\"
$destination = "c:\destination\"
foreach ($filepath in [System.IO.Directory]::EnumerateFiles($path,"xyz.config","AllDirectories"))
{
$file = New-Object System.IO.FileInfo($filepath)
if(Test-Path $file)
{
write-host $file.FullName
copy $file $destination
Write-Host 'Copied' $file ' to ' $destination
}
}
Output:
C:\Users\user1\Desktop\Config Rework\xyz\xyz.config
Copied C:\Users\user1\Desktop\Config Rework\xyz\xyz.config to c:\destination\
This has looped through the child folders under C:\Users\user1\Desktop\Config Rework, checked if xyz.config exists and then copied it to the destination folder.
Note that if your directory looks as follows:
xyz.config under xyz folder will take precedence as it will loop through the child folder.

Powershell + EWS script to move all text messages to Inbox/SMS subfolder

I'm hoping someone more experienced than me can post a Powershell script example (using the simplest possible method) that will...
Identify all messages that use "Text Message" OR "Multimedia Message" forms... then, move them to the Inbox/SMS subfolder.
Basically, I'm just trying to reproduce what my Outlook 2010 Rule does, except via command line.
If there's a pre-made cmdlet that does this already; with an example of what Im trying to do, that would be ideal.
You should be able to do that with something like this
$MailboxName = $args[0]
## Load Managed API dll
Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.1\Microsoft.Exchange.WebServices.dll"
## Set Exchange Version
$ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2
## Create Exchange Service Object
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)
## Set Credentials to use two options are availible Option1 to use explict credentials or Option 2 use the Default (logged On) credentials
#Credentials Option 1 using UPN for the windows Account
$psCred = Get-Credential
$creds = New-Object System.Net.NetworkCredential($psCred.UserName.ToString(),$psCred.GetNetworkCredential().password.ToString())
$service.Credentials = $creds
#Credentials Option 2
#service.UseDefaultCredentials = $true
## Choose to ignore any SSL Warning issues caused by Self Signed Certificates
## Code From http://poshcode.org/624
## Create a compilation environment
$Provider=New-Object Microsoft.CSharp.CSharpCodeProvider
$Compiler=$Provider.CreateCompiler()
$Params=New-Object System.CodeDom.Compiler.CompilerParameters
$Params.GenerateExecutable=$False
$Params.GenerateInMemory=$True
$Params.IncludeDebugInformation=$False
$Params.ReferencedAssemblies.Add("System.DLL") | Out-Null
$TASource=#'
namespace Local.ToolkitExtensions.Net.CertificatePolicy{
public class TrustAll : System.Net.ICertificatePolicy {
public TrustAll() {
}
public bool CheckValidationResult(System.Net.ServicePoint sp,
System.Security.Cryptography.X509Certificates.X509Certificate cert,
System.Net.WebRequest req, int problem) {
return true;
}
}
}
'#
$TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)
$TAAssembly=$TAResults.CompiledAssembly
## We now create an instance of the TrustAll and attach it to the ServicePointManager
$TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
[System.Net.ServicePointManager]::CertificatePolicy=$TrustAll
## end code from http://poshcode.org/624
## Set the URL of the CAS (Client Access Server) to use two options are availbe to use Autodiscover to find the CAS URL or Hardcode the CAS to use
#CAS URL Option 1 Autodiscover
$service.AutodiscoverUrl($MailboxName,{$true})
"Using CAS Server : " + $Service.url
#CAS URL Option 2 Hardcoded
#$uri=[system.URI] "https://casservername/ews/exchange.asmx"
#$service.Url = $uri
## Optional section for Exchange Impersonation
#$service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName)
function FolderIdFromPath{
param (
$FolderPath = "$( throw 'Folder Path is a mandatory Parameter' )"
)
process{
## Find and Bind to Folder based on Path
#Define the path to search should be seperated with \
#Bind to the MSGFolder Root
$folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)
$tfTargetFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
#Split the Search path into an array
$fldArray = $FolderPath.Split("\")
#Loop through the Split Array and do a Search for each level of folder
for ($lint = 1; $lint -lt $fldArray.Length; $lint++) {
#Perform search based on the displayname of each folder level
$fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1)
$SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$fldArray[$lint])
$findFolderResults = $service.FindFolders($tfTargetFolder.Id,$SfSearchFilter,$fvFolderView)
if ($findFolderResults.TotalCount -gt 0){
foreach($folder in $findFolderResults.Folders){
$tfTargetFolder = $folder
}
}
else{
"Error Folder Not Found"
$tfTargetFolder = $null
break
}
}
if($tfTargetFolder -ne $null){
return $tfTargetFolder.Id.UniqueId.ToString()
}
}
}
$TextMessageClass = "IPM.Note.Mobile.SMS"
$MMSMessageClass = "IPM.Note.Mobile.MMS"
$sfItemSearchFilter1 = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::ItemClass,$TextMessageClass)
$sfItemSearchFilter2 = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::ItemClass,$MMSMessageClass)
#SearchFilter collection Or
$sfCollection = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::Or);
$sfCollection.Add($sfItemSearchFilter1)
$sfCollection.Add($sfItemSearchFilter2)
# Bind to the Inbox Folder
$folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
$Inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
# Get Folder to Move Item to
$fldId = FolderIdFromPath -FolderPath "\Inbox\SMS"
$SubFolderId = new-object Microsoft.Exchange.WebServices.Data.FolderId($fldId)
$SubFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$SubFolderId)
$Itemids = #()
if($SubFolder -ne $null){
#Define ItemView to retrive just 1000 Items
$ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)
$fiItems = $null
do{
$fiItems = $service.FindItems($Inbox.Id,$sfCollection,$ivItemView)
#[Void]$service.LoadPropertiesForItems($fiItems,$psPropset)
foreach($Item in $fiItems.Items){
Write-Host ("Moving " + $Item.Subject)
$Itemids += $Item
}
$ivItemView.Offset += $fiItems.Items.Count
}while($fiItems.MoreAvailable -eq $true)
#Total Items Processed Varible
$nmbProcessed = 0
if($Itemids.Count -gt 0){
write-host ("Move " + $Itemids.Count + " Items")
#Create Collection for Move Batch
$type = ("System.Collections.Generic.List"+'`'+"1") -as "Type"
$type = $type.MakeGenericType("Microsoft.Exchange.WebServices.Data.ItemId" -as "Type")
$BatchItemids = [Activator]::CreateInstance($type)
#Varible to Track BatchSize
$batchSize = 0
foreach($iiID in $Itemids){
$nmbProcessed++
$BatchItemids.Add($iiID.Id)
if($iiID.Size -ne $null){
$batchSize += $iiID.Size
}
#if BatchCount greator then 50 or larger the 10 MB Move Batch
if($BatchItemids.Count -eq 50 -bor $batchSize -gt (10*1MB)){
$Result = $null
$Result = $service.MoveItems($BatchItemids,$SubFolder.Id)
[INT]$collectionCount = 0
[INT]$Rcount = 0
[INT]$Errcount = 0
if($Result -ne $null){
foreach ($res in $Result){
if ($res.Result -eq [Microsoft.Exchange.WebServices.Data.ServiceResult]::Success){
$Rcount++
}
else{
$Errcount++
}
$collectionCount++
}
}
else{
Write-Host -foregroundcolor red ("Move Result Null Exception")
}
Write-host ($Rcount.ToString() + " Items Moved Successfully " + "Total Processed " + $nmbProcessed + " Total Folder Items " + $Itemids.Count)
if($Errcount -gt 0){
Write-Host -foregroundcolor red ($Errcount.ToString() + " Error failed Moved")
}
$BatchItemids.Clear()
$batchSize = 0
}
}
if($BatchItemids.Count -gt 0){
$Result = $service.MoveItems($BatchItemids,$SubFolder.Id)
[INT]$Rcount = 0
[INT]$Errcount = 0
foreach ($res in $Result){
if ($res.Result -eq [Microsoft.Exchange.WebServices.Data.ServiceResult]::Success){
$Rcount++
}
else{
$Errcount++
}
}
Write-host ($Rcount.ToString() + " Items Moved Successfully")
if($Errcount -gt 0){
Write-Host -foregroundcolor red ($Errcount.ToString() + " Error failed Moved")
}
}
}
}
Cheers
Glen

Categories