I'm trying to delete an user in Active Directory via C#.When I attempt to run the following the code,I got an error.
Error Message:
A local error has occurred
Code:
DirectoryEntry ent = new DirectoryEntry("LDAP://192.168.1.99/OU=FIRMA");
ent.Username = "idm\administrator";
ent.Password = "123123QQ";
DirectorySearcher dsrc = new DirectorySearcher(ent);
dsrc.Filter = string.Format("(&(objectCategory=user)(SAMAccountName=adKullaniciadi))");
DirectoryEntry silsunuya = ent.Children.Find("CN=adKullaniciadi","objectClass=person");
ent.Children.Remove(silsunuya);
ent.Close();
silsunuya.Close();
dsrc.Dispose();
I have an ASP.Net website running local that our IT team uses to delete AD accounts, and it seems to work ok. I remember when I was developing this application there were a lot of nuances I had to deal with, which can make it painful to figure out what's going on with AD. Here is the code I am using (in VB.Net):
Public Shared Function GetUser(ByVal username As String) As DirectoryEntry
If String.IsNullOrEmpty(username) Then Return Nothing
Dim path As String = ConfigurationManager.ConnectionStrings("ADConnectionString").ConnectionString
Dim ds As New DirectorySearcher(path)
ds.Filter = "(&(objectClass=user)(sAMAccountName=" + username + "))"
ds.PropertiesToLoad.Add("sAMAccountName") ' username
ds.PropertiesToLoad.Add("mail") ' e-mail address
ds.PropertiesToLoad.Add("description") ' Bureau ID
ds.PropertiesToLoad.Add("company") ' company name
ds.PropertiesToLoad.Add("givenname") ' first name
ds.PropertiesToLoad.Add("sn") ' last name
ds.PropertiesToLoad.Add("name") ' client name
ds.PropertiesToLoad.Add("cn") ' common name
ds.PropertiesToLoad.Add("dn") ' display name
ds.PropertiesToLoad.Add("pwdLastSet")
ds.SearchScope = SearchScope.Subtree
Dim results As SearchResult = ds.FindOne
If results IsNot Nothing Then
Return New DirectoryEntry(results.Path)
Else
Return Nothing
End If
End Function
Public Shared Sub DeleteUser(ByVal username As String, Optional ByVal useImpersonation As Boolean = False)
Dim user As DirectoryEntry = GetUser(username)
Dim ou As DirectoryEntry = user.Parent
ou.Children.Remove(user)
ou.CommitChanges()
End Sub
Looking at your code, here are some ideas that come to mind:
Try using dsrc.PropertiesToLoad.Add("sAMAccountName")
Try adding a call to ent.CommitChanges()
Can you verify the path and credentials are correct, say, using a command-line AD query tool?
Can you determine specifically what line the error occurs on?
Related
I'm trying to use this code to convert a Windows username (in the classic .\username form) to a SID object:
NTAccount account = new NTAccount(".\\MyUser");
SecurityIdentifier sid = (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));
However, I keep getting the following exception when executing the last instruction:
System.Security.Principal.IdentityNotMappedException: 'Some or all
identity references could not be translated.'
What am I doing wrong?
Answering my own question after some trial and error:
The code is correct, but the Translate function doesn't seem to support the shorthand . to indicate the account is local and not in a domain. So in case you have a username that starts with .\ you need to replace the dot with the machine name. The following code works correctly:
public static SecurityIdentifier usernameToSid(string user)
{
if (user.StartsWith(#".\"))
{
user = user.Replace(#".\", Environment.MachineName + #"\");
}
NTAccount account = new NTAccount(user);
return (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));
}
I'm writing a remote log out tool for the school I attend. As system admins, we use it to log out users after our on-campus labs have closed to make sure that all the computers get updates at night. With windows 7, the tool we have now works fine. But we're updating to windows 10 for all of our machines and the tool has mysteriously stopped functioning. It's written in VB.net as of right now (open to a change to c# if needed). Currently we have 2 main functions for the program:
Private Sub LogOut()
Dim AdminAccount As String = txtUsr.Text
Dim AdminDomain As String = txtDomain.Text
Dim AdminPassword As String = txtPwd.Text
Dim ShutDownLocal As String = "c:\bin\"
Dim LogOutProgram As String = "c:\bin\Logout.cmd"
Dim TargetMachine As String = cboDom.Text & ComboBox1.Text & "p" & txtMachine.Text & txtDomain.Text
Dim ShutDownCommand As String = "shutdown -t 300 /r /m \\" & TargetMachine
If RunAs.RunAs(AdminAccount, AdminPassword, AdminDomain, ShutDownCommand, ShutDownLocal) Then
Status.Text = "5 Minute Logout sent to machine"
End If
End Sub
and
Public Shared Function RunAs(ByVal UserName As String, _
ByVal Password As String, _
ByVal DomainName As String, _
ByVal CommandLine As String, _
ByVal StartIn As String) As Boolean
Dim iRet As Integer
Dim si As New STARTUPINFO
Dim pi As PROCESS_INFORMATION
si.cb = Marshal.SizeOf(si)
si.wShowWindow = 0
iRet = CreateProcessWithLogonW(UserName, DomainName, Password, _
LOGON_WITH_PROFILE, Nothing, CommandLine, _
NORMAL_PRIORITY_CLASS, 0, StartIn, si, pi)
If iRet = 0 Then
MessageBox.Show("Password incorrect.", "Error")
Return False
Else
CloseHandle(pi.hThread)
CloseHandle(pi.hProcess)
Return True
End If
End Function
Currently this functions absolutely fine on windows 7 machines but for attempting it on windows 10 machines we either get "access denied(5)" or "The entered computer name is not valid or remote shutdown is not supported on the target computer. Check the name and then try again or contact your system administrator.(53)"
I already checked with the administrator and he said that it is enabled. We use a domain level firewall so the individual computers aren't rejecting the connection. Every machine has the same administrator groups (Which I am using the credentials for every attempt). I'm not sure of any other solutions to look into. Sorry for the wall of text, any solutions can be tested for the most part. No third party software unfortunately.
Thanks!
I am creating a windows service to save current username and logon time in a CSV file. But when I install the service, the file is just created, not details are written to it, and that file is set to read-only mode. what is the problem in my code?
My code:
Imports System.IO
Imports System.Text
Imports System.DirectoryServices
Imports System.DirectoryServices.AccountManagement
Imports System.Diagnostics
Public Class LoginService1
Protected Overrides Sub OnStart(ByVal args() As String)
Dim win As System.Security.Principal.WindowsIdentity
win = System.Security.Principal.WindowsIdentity.GetCurrent()
Dim Logon_UserName = win.Name.Substring(win.Name.IndexOf("\") + 1)
Dim pc As New PrincipalContext(ContextType.Machine, My.Computer.Name)
Dim uc As UserPrincipal = UserPrincipal.FindByIdentity(pc, Logon_UserName)
Dim str As String = ""
Try
Dim sr As New StreamReader("c:\logondetails.csv")
str = sr.ReadToEnd()
sr.Close()
sr.Dispose()
Catch ex As Exception
End Try
Try
Dim sw As New StreamWriter("c:\logondetails.csv")
Str += Logon_UserName & "," & uc.LastLogon.Value.ToString
sw.WriteLine(str)
sw.Close()
sw.Dispose()
Catch ex As Exception
End Try
End Sub
Protected Overrides Sub OnStop()
' Add code here to perform any tear-down necessary to stop your service.'
End Sub
End Class
There are many ways to fix what you are doing.
For 1, you dont need to read in the entire file to append to the end of it. For example
using(var stream = File.AppendText(fileName))
{
stream.Write(string);
stream.Close();
}
But you are going to have issues with concurrent access to the file. You'd be better off using a logging framework, such as log4net or microsoft logging block, and then just
Logger.Info(yourstring);
and be done with it. The framework will handle the file access issues.
I'm trying to find a way to get mail attachments (programaticaly) , and then open it... can someone tell me how to do this or point me to a right direction?
This is a VBA script (use in a Macro in Outlook) which will loop over all attachments in all selected items in the current folder and Save them to disk.
It should get you started and I don't think it would take much to add some kind of process launch rather than save logic to it.
Public Sub SaveAttachments()
'Note, this assumes you are in the a folder with e-mail messages when you run it.
'It does not have to be the inbox, simply any folder with e-mail messages
Dim Exp As Outlook.Explorer
Dim Sel As Outlook.Selection
Dim AttachmentCnt As Integer
Dim AttTotal As Integer
Dim MsgTotal As Integer
Dim outputDir As String
Dim outputFile As String
Dim fileExists As Boolean
Dim cnt As Integer
'Requires reference to Microsoft Scripting Runtime (SCRRUN.DLL)
Dim fso As FileSystemObject
Set Exp = Application.ActiveExplorer
Set Sel = Exp.Selection
Set fso = New FileSystemObject
outputDir = "C:\Path"
If outputDir = "" Then
MsgBox "You must pick an directory to save your files to. Exiting SaveAttachments.", vbCritical, "SaveAttachments"
Exit Sub
End If
Dim att As Attachment
'Loop thru each selected item in the inbox
For cnt = 1 To Sel.Count
'If the e-mail has attachments...
If Sel.Item(cnt).Attachments.Count > 0 Then
MsgTotal = MsgTotal + 1
'For each attachment on the message...
For AttachmentCnt = 1 To Sel.Item(cnt).Attachments.Count
'Get the attachment
Set att = Sel.Item(cnt).Attachments.Item(AttachmentCnt)
outputFile = att.FileName
outputFile = Format(Sel.Item(cnt).ReceivedTime, "yyyy-mm-dd_hhmmss - ") + outputFile
fileExists = fso.fileExists(outputDir + outputFile)
'Save it to disk if the file does not exist
If fileExists = False Then
att.SaveAsFile (outputDir + outputFile)
AttTotal = AttTotal + 1
End If
Set att = Nothing
Sel.Item(cnt).Close (Outlook.OlInspectorClose.olDiscard)
Next
End If
Next
'Clean up
Set Sel = Nothing
Set Exp = Nothing
Set fso = Nothing
'Let user know we are done
Dim doneMsg As String
doneMsg = "Completed saving " + Format$(AttTotal, "#,0") + " attachments in " + Format$(MsgTotal, "#,0") + " Messages."
MsgBox doneMsg, vbOKOnly, "Save Attachments"
Exit Sub
ErrorHandler:
Dim errMsg As String
errMsg = "An error has occurred. Error " + Err.Number + " " + Err.Description
Dim errResult As VbMsgBoxResult
errResult = MsgBox(errMsg, vbAbortRetryIgnore, "Error in Save Attachments")
Select Case errResult
Case vbAbort
Exit Sub
Case vbRetry
Resume
Case vbIgnore
Resume Next
End Select
End Sub
Look for the COM-reference of Outlook.
You can also use a macro written in vba to do this.
Is there any way to set a custom Icon of an Outlook folder or subfolder using Outlook object model?
As from Outlook 2010 you can use MAPIFolder.SetCUstomIcon as described above.
I have had the same challenge recently and found a nice snippet of VBA code at
Change Outlook folders colors possible?:
joelandre Jan 12, 2015 at 9:13 PM
Unzip the file icons.zip to C:\icons
Define the code below as Visual Basic Macros
Adapt the function ColorizeOutlookFolders according to your needs Text
Function GetFolder(ByVal FolderPath As String) As Outlook.folder
' Returns an Outlook folder object basing on the folder path
'
Dim TempFolder As Outlook.folder
Dim FoldersArray As Variant
Dim i As Integer
On Error GoTo GetFolder_Error
'Remove Leading slashes in the folder path
If Left(FolderPath, 2) = "\\" Then
FolderPath = Right(FolderPath, Len(FolderPath) - 2)
End If
'Convert folderpath to array
FoldersArray = Split(FolderPath, "\")
Set TempFolder = Application.Session.Folders.Item(FoldersArray(0))
If Not TempFolder Is Nothing Then
For i = 1 To UBound(FoldersArray, 1)
Dim SubFolders As Outlook.Folders
Set SubFolders = TempFolder.Folders
Set TempFolder = SubFolders.Item(FoldersArray(i))
If TempFolder Is Nothing Then
Set GetFolder = Nothing
End If
Next
End If
'Return the TempFolder
Set GetFolder = TempFolder
Exit Function GetFolder_Error:
Set GetFolder = Nothing
Exit Function End Function Sub ColorizeOneFolder(FolderPath As String, FolderColour As String)
Dim myPic As IPictureDisp
Dim folder As Outlook.folder
Set folder = GetFolder(FolderPath)
Set myPic = LoadPicture("C:\icons\" + FolderColour + ".ico")
If Not (folder Is Nothing) Then
' set a custom icon to the folder
folder.SetCustomIcon myPic
'Debug.Print "setting colour to " + FolderPath + " as " + FolderColour
End If End Sub
Sub ColorizeFolderAndSubFolders(strFolderPath As String, strFolderColour As String)
' this procedure colorizes the foler given by strFolderPath and all subfolfers
Dim olProjectRootFolder As Outlook.folder
Set olProjectRootFolder = GetFolder(strFolderPath)
Dim i As Long
Dim olNewFolder As Outlook.MAPIFolder
Dim olTempFolder As Outlook.MAPIFolder
Dim strTempFolderPath As String
' colorize folder
Call ColorizeOneFolder(strFolderPath, strFolderColour)
' Loop through the items in the current folder.
For i = olProjectRootFolder.Folders.Count To 1 Step -1
Set olTempFolder = olProjectRootFolder.Folders(i)
strTempFolderPath = olTempFolder.FolderPath
'prints the folder path and name in the VB Editor's Immediate window
'Debug.Print sTempFolderPath
' colorize folder
Call ColorizeOneFolder(strTempFolderPath, strFolderColour)
Next
For Each olNewFolder In olProjectRootFolder.Folders
' recursive call
'Debug.Print olNewFolder.FolderPath
Call ColorizeFolderAndSubFolders(olNewFolder.FolderPath, strFolderColour)
Next
End Sub
Sub ColorizeOutlookFolders()
Call ColorizeFolderAndSubFolders("\\Personal\Documents\000-Mgmt-CH\100-People", "blue")
Call ColorizeFolderAndSubFolders("\\Personal\Documents\000-Mgmt-CH\200-Projects","red")
Call ColorizeFolderAndSubFolders("\\Personal\Documents\000-Mgmt-CH\500-Meeting", "green")
Call ColorizeFolderAndSubFolders("\\Personal\Documents\000-Mgmt-CH\800-Product", "magenta")
Call ColorizeFolderAndSubFolders("\\Personal\Documents\000-Mgmt-CH\600-Departments", "grey")
Call ColorizeFolderAndSubFolders("\\Mailbox - Dan Wilson\Inbox\Customers", "grey")
End Sub
In the object ThisOutlookSession, define the following function:
Private Sub Application_Startup()
ColorizeOutlookFolders
End Sub
and
In order to NOT color sub-folders, you can use the function
ColorizeOneFolder instead of ColorizeFolderAndSubFolders e.g.
Sub ColorizeOutlookFolders()
Call ColorizeOneFolder ("\\Personal\Documents\000-Mgmt-CH\100-People", "blue")
Call ColorizeOneFolder ("\\Personal\Documents\000-Mgmt-CH\200-Projects", "red")
Call ColorizeOneFolder ("\\Personal\Documents\000-Mgmt-CH\500-Meeting", "green")
Call ColorizeOneFolder ("\\Personal\Documents\000-Mgmt-CH\800-Product", "magenta")
Call ColorizeOneFolder ("\\Personal\Documents\000-Mgmt-CH\600-Departments", "grey")
Call ColorizeOneFolder ("\\Mailbox - Dan Wilson\Inbox\Customers", "grey")
End Sub
When you move sub-folders between folders, they should retain their
color only until the next time you restart Outlook.
From what I have read this is unfortunately not possible in Outlook 2007.
It is possible in Outlook 2010 using MAPIFolder.SetCustomIcon. See MSDN for more details: http://msdn.microsoft.com/en-us/library/ff184775.aspx
Switching the list of MAPIFolder methods between 2010 and 2007 on the following MSDN webpage shows the SetCustomIcon method for 2010 only: http://msdn.microsoft.com/en-us/library/bb645002.aspx