'3. Implementation/C#'에 해당되는 글 17건
- 2013.12.10 Run a sudo command using RunCommand
- 2012.02.20 ILMerge : merge multiple .NET assemblies into a single assembly
- 2012.02.17 How to load an assembly at runtime that is located in a folder that is not the bin folder of the application
- 2012.01.31 재귀와 반복
- 2011.08.16 How to invoke with more than one parameter
- 2011.01.03 CustomQueryInterface - IDispatch and Aggregation
- 2010.12.08 ListView 깜박임 제거
- 2010.12.08 비동기로 실행하기
- 2010.10.22 하드웨어 정보 가져오기 1
- 2010.04.26 어셈블리 보기: ILDASM
- 2010.04.23 Snoop: a WPF utility
- 2010.04.22 WPF 와 Windows Form Control 간의 상호 운용
- 2010.04.21 How to register .NET components with COM
- 2010.04.01 AutoDual ClassInterfaceType을 사용하지 마십시오
- 2010.04.01 Writing an ActiveX Control in .NET
- 2010.03.26 C# Delegate 사용하기
- 2010.03.25 A Simple C# Global Low Level Keyboard Hook
I had googled for this and got the useful information:
Unfortunalty, when yo execute a command using RunCommand you cannot run it using su or sudo.
The reason is that command executes as one single unit and have no knowledge or previous commands or shell it executes in.
It seems that SSH Server creates context for command execution, executes it and the deletes this context.
One thing you can try to execute the command is shell object, this way it creates shell, pretty much like you do with putty, and lets you send text and get text back, which you can analyze later.
Here is alternative to run a command
client.RunCommand("echo \"userpwd\" | sudo -S command").Execute()
-S key tells sudo to take password from stdin, which is piped from the previous echo command
Source: https://sshnet.codeplex.com/discussions/269667
If sudo command doesn't prompt password, output will be like the following:
administrator@ubuntu:~$ echo "test" | sudo -S ls [sudo] password for administrator: Sorry, try again. [sudo] password for administrator: Sorry, try again. [sudo] password for administrator: Sorry, try again. sudo: 3 incorrect password attempts
If you use RunCommand, it will be ok because there is no connection (or context) between each RunCommand. I mean that sudo command using RunCommand will prompt password all the time.
Here is Sample codes.
using (SshClient client = new SshClient(connectionInfo)) { client.Connect(); using (var cmd = client.CreateCommand("echo \"password\" | sudo -S ls")) { cmd.CommandTimeout = TimeSpan.FromSeconds(10); var asynch = cmd.BeginExecute(); var reader = new StreamReader(cmd.OutputStream); while (!asynch.IsCompleted) { var result = reader.ReadToEnd(); if (string.IsNullOrEmpty(result)) continue; Console.Write(result); } cmd.EndExecute(asynch); client.Disconnect(); } }
ILMerge : merge multiple .NET assemblies into a single assembly

아래 링크에서 최신 버전을 받아서 설치합니다.
http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=17630
설치가 완료되면
ilmerge /target:winexe /out:test.exe MyApp.exe lib1.dll lib2.dll lib3.dll
결과가 dll 이면 /target:library 로 하면 됩니다. 그리고 자세한 옵션은 Ilmerge 의 명령어 도움말을 보시면 됩니다.
훌륭합니다, Microsoft~!
참고:
http://research.microsoft.com/en-us/people/mbarnett/ILMerge.aspx
http://stackoverflow.com/questions/4635573/merging-dll-files-with-ilmerge-failing-to-work
How to load an assembly at runtime that is located in a folder that is not the bin folder of the application

B.dll
Common.dll
이 있습니다. Common.dll 은 A, B 모두에게 사용되기 때문에 같이 개발되고 빌드됩니다. 하지만 A.dll 과 B.dll 은 각기 다른 목적을 가지고 있기 때문에 다른 위치에 배포됩니다. 예를 들어
Test1/
Common.dll
Common.dll
이렇게 배포를 했는데 문제가 생겼습니다. Test1, Test2 는 각기 다르게 배포되고 Common.dll 은 여러버전이 존재할 수 있습니다. A 가 처음 로딩될 때는 Test1 의 Common.dll 이 정상적으로 로딩되었으나, 그 다음에 B가 로디오될 때는 Test2 에 있는 Common.dll 이 아니라 이미 로딩되어 있는 Test1/Common.dll 을 그대로 사용하는 문제였습니다. (A.dll 과 B.dll 은 모두 COM 이기 때문에 배포시 'regasm.exe /codebase a.dll" 과 같이 codebase 로 글로벌하게 등록되어 있습니다.)
이 문제를 수정하기 위해 자료를 찾다가 MS 에서 제공하는 아래 링크 정보를 찾았습니다.
http://support.microsoft.com/kb/837908
3가지 방법을 소개 하고 있는데 그중에 3번째인 AssemblyResolve 이벤트라는 재밌는 녀석이 나옵니다.
핸들러 등록 방법
AppDomain currentDomain = AppDomain.CurrentDomain; currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
핸들러 코드 예제
private Assembly MyResolveEventHandler(object sender,ResolveEventArgs args) { //This handler is called only when the common language runtime tries to bind to the assembly and fails. //Retrieve the list of referenced assemblies in an array of AssemblyName. Assembly MyAssembly,objExecutingAssemblies; string strTempAssmbPath=""; objExecutingAssemblies=Assembly.GetExecutingAssembly(); AssemblyName [] arrReferencedAssmbNames=objExecutingAssemblies.GetReferencedAssemblies(); //Loop through the array of referenced assembly names. foreach(AssemblyName strAssmbName in arrReferencedAssmbNames) { //Check for the assembly names that have raised the "AssemblyResolve" event. if(strAssmbName.FullName.Substring(0, strAssmbName.FullName.IndexOf(","))==args.Name.Substring(0, args.Name.IndexOf(","))) { //Build the path of the assembly from where it has to be loaded. strTempAssmbPath="C:\\Myassemblies\\"+args.Name.Substring(0,args.Name.IndexOf(","))+".dll"; break; } } //Load the assembly from the specified path. MyAssembly = Assembly.LoadFrom(strTempAssmbPath); //Return the loaded assembly. return MyAssembly; }
주의: 위 코드가 제기된 문제를 해결했다는 건 아닙니다. 아직 적용을 해보지 못했습니다.
왜 이런 재귀와 반복의 변환을 고민하게 되었냐면은 재귀로 작성했던 기능이 있는데 이 기능이 함수 하나로만 작성되어야할 필요가 생겼습니다. 그래서 내키지 않았지만 어쩔수 없이 반복으로 재작성하였습니다. 해놓고 보니 나쁘지 않더군요.
재귀와 반복 구현에 대해 마이크로소프트에서 제공하는 아주 좋은 예제가 있어 공유해 드립니다.
출처: http://msdn.microsoft.com/ko-kr/library/bb513869.aspx
디렉토리 탐색하기
1. 재귀를 이용한 방법 (Recusive File Search)
public class RecursiveFileSearch { static System.Collections.Specialized.StringCollection log = new System.Collections.Specialized.StringCollection(); static void Main() { // Start with drives if you have to search the entire computer. string[] drives = System.Environment.GetLogicalDrives(); foreach (string dr in drives) { System.IO.DriveInfo di = new System.IO.DriveInfo(dr); // Here we skip the drive if it is not ready to be read. This // is not necessarily the appropriate action in all scenarios. if (!di.IsReady) { Console.WriteLine("The drive {0} could not be read", di.Name); continue; } System.IO.DirectoryInfo rootDir = di.RootDirectory; WalkDirectoryTree(rootDir); } // Write out all the files that could not be processed. Console.WriteLine("Files with restricted access:"); foreach (string s in log) { Console.WriteLine(s); } // Keep the console window open in debug mode. Console.WriteLine("Press any key"); Console.ReadKey(); } static void WalkDirectoryTree(System.IO.DirectoryInfo root) { System.IO.FileInfo[] files = null; System.IO.DirectoryInfo[] subDirs = null; // First, process all the files directly under this folder try { files = root.GetFiles("*.*"); } // This is thrown if even one of the files requires permissions greater // than the application provides. catch (UnauthorizedAccessException e) { // This code just writes out the message and continues to recurse. // You may decide to do something different here. For example, you // can try to elevate your privileges and access the file again. log.Add(e.Message); } catch (System.IO.DirectoryNotFoundException e) { Console.WriteLine(e.Message); } if (files != null) { foreach (System.IO.FileInfo fi in files) { // In this example, we only access the existing FileInfo object. If we // want to open, delete or modify the file, then // a try-catch block is required here to handle the case // where the file has been deleted since the call to TraverseTree(). Console.WriteLine(fi.FullName); } // Now find all the subdirectories under this directory. subDirs = root.GetDirectories(); foreach (System.IO.DirectoryInfo dirInfo in subDirs) { // Resursive call for each subdirectory. WalkDirectoryTree(dirInfo); } } } }
2. 반복을 이용한 방법 (Stack based Iteration)
public class StackBasedIteration { static void Main(string[] args) { // Specify the starting folder on the command line, or in // Visual Studio in the Project > Properties > Debug pane. TraverseTree(args[0]); Console.WriteLine("Press any key"); Console.ReadKey(); } public static void TraverseTree(string root) { // Data structure to hold names of subfolders to be // examined for files. Stack<string> dirs = new Stack<string>(20); if (!System.IO.Directory.Exists(root)) { throw new ArgumentException(); } dirs.Push(root); while (dirs.Count > 0) { string currentDir = dirs.Pop(); string[] subDirs; try { subDirs = System.IO.Directory.GetDirectories(currentDir); } // An UnauthorizedAccessException exception will be thrown if we do not have // discovery permission on a folder or file. It may or may not be acceptable // to ignore the exception and continue enumerating the remaining files and // folders. It is also possible (but unlikely) that a DirectoryNotFound exception // will be raised. This will happen if currentDir has been deleted by // another application or thread after our call to Directory.Exists. The // choice of which exceptions to catch depends entirely on the specific task // you are intending to perform and also on how much you know with certainty // about the systems on which this code will run. catch (UnauthorizedAccessException e) { Console.WriteLine(e.Message); continue; } catch (System.IO.DirectoryNotFoundException e) { Console.WriteLine(e.Message); continue; } string[] files = null; try { files = System.IO.Directory.GetFiles(currentDir); } catch (UnauthorizedAccessException e) { Console.WriteLine(e.Message); continue; } catch (System.IO.DirectoryNotFoundException e) { Console.WriteLine(e.Message); continue; } // Perform the required action on each file here. // Modify this block to perform your required task. foreach (string file in files) { try { // Perform whatever action is required in your scenario. System.IO.FileInfo fi = new System.IO.FileInfo(file); Console.WriteLine("{0}: {1}, {2}", fi.Name, fi.Length, fi.CreationTime); } catch (System.IO.FileNotFoundException e) { // If file was deleted by a separate application // or thread since the call to TraverseTree() // then just continue. Console.WriteLine(e.Message); continue; } } // Push the subdirectories onto the stack for traversal. // This could also be done before handing the files. foreach (string str in subDirs) dirs.Push(str); } }}
How to invoke with more than one parameter

public void DoSomething(string foo, int bar) { if (this.InvokeRequired) { this.Invoke((MethodInvoker)delegate { DoSomething(foo,bar); }); return; } // do something with foo and bar this.Text = foo; Console.WriteLine(bar); }
출처: http://stackoverflow.com/questions/729430/c-how-to-invoke-with-more-than-one-parameter
CustomQueryInterface - IDispatch and Aggregation

In this sample, we will show an implementation of ICustomQueryInterface through
- a managed IDispatch implementation that overrides the default IDispatch implementation by the CLR
- a managed COM aggregation system where both Outer and Inner objects are managed objects
class ListViewNF : System.Windows.Forms.ListView { public ListViewNF() { //Activate double buffering this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); //Enable the OnNotifyMessage event so we get a chance to filter out // Windows messages before they get to the form's WndProc this.SetStyle(ControlStyles.EnableNotifyMessage, true); } protected override void OnNotifyMessage(Message m) { //Filter out the WM_ERASEBKGND message if(m.Msg != 0x14) { base.OnNotifyMessage(m); } } }
public class FormFoo : Form { Label label = new Label(); public static void Main() { Application.Run(new FormFoo()); } public FormFoo() { InitializeComponent(); Thread t = new Thread(new ThreadStart(ChangeLabel)); t.Start(); } private void ChangeLabel() { for (int i = 0; i<100; ++i) { SetLabelText(i); Thread.Sleep(1000); } } private delegate void SetLabelTextDelegate(int number); private void SetLabelText(int number) { // label.Text = number.ToString(); // Do NOT do this, as we are on a different thread. // Check if we need to call BeginInvoke. if (this.InvokeRequired) { // Pass the same function to BeginInvoke, // but the call would come on the correct // thread and InvokeRequired will be false. this.BeginInvoke(new SetLabelTextDelegate(SetLabelText), new object[] {number}); return; } label.Text = number.ToString(); } }
Why and when to call BeginInvoke
With all that stuff inside our head now, we can easily figure out the reason for the existence of BeginInvoke
. It essentially does a PostMessage
. Whenever you want to update a control from a thread that didn't create it, instead of directly calling the method/property to update it, you need to wrap it in a BeginInvoke
call. According to MSDN: "There are four methods on a control that are safe to call from any thread: Invoke
,BeginInvoke
, EndInvoke
, and CreateGraphics
. For all other method calls, you should use one of the invoke methods to marshal the call to the control's thread". One of the invoke methods, you say, what are the others? Well, the Control
class provides one property and two methods to do the stuff we discussed.
InvokeRequired
: Thisbool
property returnstrue
if the thread on which this property is called is not the thread that created this control. Basically, ifInvokeRequired
returnstrue
, you need to call one of the two Invoke methods.
BeginInvoke
: This is a functionally similar to thePostMessage
API function. It posts a message to the queue and returns immediately without waiting for the message to be processed.BeginInvoke
returns anIAsyncResult
, just like theBeginInvoke
method on any delegate. And you can useIAsyncResult
to wait for the message to be processed, just as usual. And you can callEndInvoke
to get return values orout
parameter values, as usual.Invoke
: This is like theSendMessage
API function in that it waits till the message gets processed, but it does not do aSendMessage
internally, it also does aPostMessage
. The difference is that it waits till the delegate is executed on the UI thread before returning. So while there is a chance for the deadlock problem to occur, you can be sure that the other problems associated withSendMessage
won't happen.Invoke
returns the value that the function wrapped by the delegate returned.
using System.Management;2. ManagementObjectSearcher 클래스 생성
ManagementObjectSearcher searcher = new ManagementObjectSearcher( "select * from " + Key);3. Key 리스트
Win32_1394Controller Win32_1394ControllerDevice Win32_Account Win32_AccountSID Win32_ACE Win32_ActionCheck Win32_AllocatedResource Win32_ApplicationCommandLine Win32_ApplicationService Win32_AssociatedBattery Win32_AssociatedProcessorMemory Win32_BaseBoard Win32_BaseService Win32_Battery Win32_Binary Win32_BindImageAction Win32_BIOS Win32_BootConfiguration Win32_Bus Win32_CacheMemory Win32_CDROMDrive Win32_CheckCheck Win32_CIMLogicalDeviceCIMDataFile Win32_ClassicCOMApplicationClasses Win32_ClassicCOMClass Win32_ClassicCOMClassSetting Win32_ClassicCOMClassSettings Win32_ClassInfoAction Win32_ClientApplicationSetting Win32_CodecFile Win32_COMApplication Win32_COMApplicationClasses Win32_COMApplicationSettings Win32_COMClass Win32_ComClassAutoEmulator Win32_ComClassEmulator Win32_CommandLineAccess Win32_ComponentCategory Win32_ComputerSystem Win32_ComputerSystemProcessor Win32_ComputerSystemProduct Win32_COMSetting Win32_Condition Win32_CreateFolderAction Win32_CurrentProbe Win32_DCOMApplication Win32_DCOMApplicationAccessAllowedSetting Win32_DCOMApplicationLaunchAllowedSetting Win32_DCOMApplicationSetting Win32_DependentService Win32_Desktop Win32_DesktopMonitor Win32_DeviceBus Win32_DeviceMemoryAddress Win32_DeviceSettings Win32_Directory Win32_DirectorySpecification Win32_DiskDrive Win32_DiskDriveToDiskPartition Win32_DiskPartition Win32_DisplayConfiguration Win32_DisplayControllerConfiguration Win32_DMAChannel Win32_DriverVXD Win32_DuplicateFileAction Win32_Environment Win32_EnvironmentSpecification Win32_ExtensionInfoAction Win32_Fan Win32_FileSpecification Win32_FloppyController Win32_FloppyDrive Win32_FontInfoAction Win32_Group Win32_GroupUser Win32_HeatPipe Win32_IDEController Win32_IDEControllerDevice Win32_ImplementedCategory Win32_InfraredDevice Win32_IniFileSpecification Win32_InstalledSoftwareElement Win32_IRQResource Win32_Keyboard Win32_LaunchCondition Win32_LoadOrderGroup Win32_LoadOrderGroupServiceDependencies Win32_LoadOrderGroupServiceMembers Win32_LogicalDisk Win32_LogicalDiskRootDirectory Win32_LogicalDiskToPartition Win32_LogicalFileAccess Win32_LogicalFileAuditing Win32_LogicalFileGroup Win32_LogicalFileOwner Win32_LogicalFileSecuritySetting Win32_LogicalMemoryConfiguration Win32_LogicalProgramGroup Win32_LogicalProgramGroupDirectory Win32_LogicalProgramGroupItem Win32_LogicalProgramGroupItemDataFile Win32_LogicalShareAccess Win32_LogicalShareAuditing Win32_LogicalShareSecuritySetting Win32_ManagedSystemElementResource Win32_MemoryArray Win32_MemoryArrayLocation Win32_MemoryDevice Win32_MemoryDeviceArray Win32_MemoryDeviceLocation Win32_MethodParameterClass Win32_MIMEInfoAction Win32_MotherboardDevice Win32_MoveFileAction Win32_MSIResource Win32_NetworkAdapter Win32_NetworkAdapterConfiguration Win32_NetworkAdapterSetting Win32_NetworkClient Win32_NetworkConnection Win32_NetworkLoginProfile Win32_NetworkProtocol Win32_NTEventlogFile Win32_NTLogEvent Win32_NTLogEventComputer Win32_NTLogEventLog Win32_NTLogEventUser Win32_ODBCAttribute Win32_ODBCDataSourceAttribute Win32_ODBCDataSourceSpecification Win32_ODBCDriverAttribute Win32_ODBCDriverSoftwareElement Win32_ODBCDriverSpecification Win32_ODBCSourceAttribute Win32_ODBCTranslatorSpecification Win32_OnBoardDevice Win32_OperatingSystem Win32_OperatingSystemQFE Win32_OSRecoveryConfiguration Win32_PageFile Win32_PageFileElementSetting Win32_PageFileSetting Win32_PageFileUsage Win32_ParallelPort Win32_Patch Win32_PatchFile Win32_PatchPackage Win32_PCMCIAController Win32_Perf Win32_PerfRawData Win32_PerfRawData_ASP_ActiveServerPages Win32_PerfRawData_ASPNET_114322_ASPNETAppsv114322 Win32_PerfRawData_ASPNET_114322_ASPNETv114322 Win32_PerfRawData_ASPNET_ASPNET Win32_PerfRawData_ASPNET_ASPNETApplications Win32_PerfRawData_IAS_IASAccountingClients Win32_PerfRawData_IAS_IASAccountingServer Win32_PerfRawData_IAS_IASAuthenticationClients Win32_PerfRawData_IAS_IASAuthenticationServer Win32_PerfRawData_InetInfo_InternetInformationServicesGlobal Win32_PerfRawData_MSDTC_DistributedTransactionCoordinator Win32_PerfRawData_MSFTPSVC_FTPService Win32_PerfRawData_MSSQLSERVER_SQLServerAccessMethods Win32_PerfRawData_MSSQLSERVER_SQLServerBackupDevice Win32_PerfRawData_MSSQLSERVER_SQLServerBufferManager Win32_PerfRawData_MSSQLSERVER_SQLServerBufferPartition Win32_PerfRawData_MSSQLSERVER_SQLServerCacheManager Win32_PerfRawData_MSSQLSERVER_SQLServerDatabases Win32_PerfRawData_MSSQLSERVER_SQLServerGeneralStatistics Win32_PerfRawData_MSSQLSERVER_SQLServerLatches Win32_PerfRawData_MSSQLSERVER_SQLServerLocks Win32_PerfRawData_MSSQLSERVER_SQLServerMemoryManager Win32_PerfRawData_MSSQLSERVER_SQLServerReplicationAgents Win32_PerfRawData_MSSQLSERVER_SQLServerReplicationDist Win32_PerfRawData_MSSQLSERVER_SQLServerReplicationLogreader Win32_PerfRawData_MSSQLSERVER_SQLServerReplicationMerge Win32_PerfRawData_MSSQLSERVER_SQLServerReplicationSnapshot Win32_PerfRawData_MSSQLSERVER_SQLServerSQLStatistics Win32_PerfRawData_MSSQLSERVER_SQLServerUserSettable Win32_PerfRawData_NETFramework_NETCLRExceptions Win32_PerfRawData_NETFramework_NETCLRInterop Win32_PerfRawData_NETFramework_NETCLRJit Win32_PerfRawData_NETFramework_NETCLRLoading Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads Win32_PerfRawData_NETFramework_NETCLRMemory Win32_PerfRawData_NETFramework_NETCLRRemoting Win32_PerfRawData_NETFramework_NETCLRSecurity Win32_PerfRawData_Outlook_Outlook Win32_PerfRawData_PerfDisk_PhysicalDisk Win32_PerfRawData_PerfNet_Browser Win32_PerfRawData_PerfNet_Redirector Win32_PerfRawData_PerfNet_Server Win32_PerfRawData_PerfNet_ServerWorkQueues Win32_PerfRawData_PerfOS_Cache Win32_PerfRawData_PerfOS_Memory Win32_PerfRawData_PerfOS_Objects Win32_PerfRawData_PerfOS_PagingFile Win32_PerfRawData_PerfOS_Processor Win32_PerfRawData_PerfOS_System Win32_PerfRawData_PerfProc_FullImage_Costly Win32_PerfRawData_PerfProc_Image_Costly Win32_PerfRawData_PerfProc_JobObject Win32_PerfRawData_PerfProc_JobObjectDetails Win32_PerfRawData_PerfProc_Process Win32_PerfRawData_PerfProc_ProcessAddressSpace_Costly Win32_PerfRawData_PerfProc_Thread Win32_PerfRawData_PerfProc_ThreadDetails_Costly Win32_PerfRawData_RemoteAccess_RASPort Win32_PerfRawData_RemoteAccess_RASTotal Win32_PerfRawData_RSVP_ACSPerRSVPService Win32_PerfRawData_Spooler_PrintQueue Win32_PerfRawData_TapiSrv_Telephony Win32_PerfRawData_Tcpip_ICMP Win32_PerfRawData_Tcpip_IP Win32_PerfRawData_Tcpip_NBTConnection Win32_PerfRawData_Tcpip_NetworkInterface Win32_PerfRawData_Tcpip_TCP Win32_PerfRawData_Tcpip_UDP Win32_PerfRawData_W3SVC_WebService Win32_PhysicalMemory Win32_PhysicalMemoryArray Win32_PhysicalMemoryLocation Win32_PNPAllocatedResource Win32_PnPDevice Win32_PnPEntity Win32_PointingDevice Win32_PortableBattery Win32_PortConnector Win32_PortResource Win32_POTSModem Win32_POTSModemToSerialPort Win32_PowerManagementEvent Win32_Printer Win32_PrinterConfiguration Win32_PrinterController Win32_PrinterDriverDll Win32_PrinterSetting Win32_PrinterShare Win32_PrintJob Win32_PrivilegesStatus Win32_Process Win32_Processor Win32_ProcessStartup Win32_Product Win32_ProductCheck Win32_ProductResource Win32_ProductSoftwareFeatures Win32_ProgIDSpecification Win32_ProgramGroup Win32_ProgramGroupContents Win32_ProgramGroupOrItem Win32_Property Win32_ProtocolBinding Win32_PublishComponentAction Win32_QuickFixEngineering Win32_Refrigeration Win32_Registry Win32_RegistryAction Win32_RemoveFileAction Win32_RemoveIniAction Win32_ReserveCost Win32_ScheduledJob Win32_SCSIController Win32_SCSIControllerDevice Win32_SecurityDescriptor Win32_SecuritySetting Win32_SecuritySettingAccess Win32_SecuritySettingAuditing Win32_SecuritySettingGroup Win32_SecuritySettingOfLogicalFile Win32_SecuritySettingOfLogicalShare Win32_SecuritySettingOfObject Win32_SecuritySettingOwner Win32_SelfRegModuleAction Win32_SerialPort Win32_SerialPortConfiguration Win32_SerialPortSetting Win32_Service Win32_ServiceControl Win32_ServiceSpecification Win32_ServiceSpecificationService Win32_SettingCheck Win32_Share Win32_ShareToDirectory Win32_ShortcutAction Win32_ShortcutFile Win32_ShortcutSAP Win32_SID Win32_SMBIOSMemory Win32_SoftwareElement Win32_SoftwareElementAction Win32_SoftwareElementCheck Win32_SoftwareElementCondition Win32_SoftwareElementResource Win32_SoftwareFeature Win32_SoftwareFeatureAction Win32_SoftwareFeatureCheck Win32_SoftwareFeatureParent Win32_SoftwareFeatureSoftwareElements Win32_SoundDevice Win32_StartupCommand Win32_SubDirectory Win32_SystemAccount Win32_SystemBIOS Win32_SystemBootConfiguration Win32_SystemDesktop Win32_SystemDevices Win32_SystemDriver Win32_SystemDriverPNPEntity Win32_SystemEnclosure Win32_SystemLoadOrderGroups Win32_SystemLogicalMemoryConfiguration Win32_SystemMemoryResource Win32_SystemNetworkConnections Win32_SystemOperatingSystem Win32_SystemPartitions Win32_SystemProcesses Win32_SystemProgramGroups Win32_SystemResources Win32_SystemServices Win32_SystemSetting Win32_SystemSlot Win32_SystemSystemDriver Win32_SystemTimeZone Win32_SystemUsers Win32_TapeDrive Win32_TemperatureProbe Win32_Thread Win32_TimeZone Win32_Trustee Win32_TypeLibraryAction Win32_UninterruptiblePowerSupply Win32_USBController Win32_USBControllerDevice Win32_UserAccount Win32_UserDesktop Win32_VideoConfiguration Win32_VideoController Win32_VideoSettings Win32_VoltageProbe Win32_WMIElementSetting Win32_WMISetting4. ManagementObjectSearcher 의 Get() 메소드 호출
foreach (ManagementObject share in searcher.Get()) { // Some Codes ... }5. Properties 속성 사용
foreach (PropertyData PC in share.Properties) { //some codes ... }
자주 활용하자.
왜 이문제를 고민했냐면, WPF 작성한 Application 을 ActiveX Control 로 재작성해야할 필요성이 생겼다. 근데 WPF 는 ActiveX Control 을 작성하지 못하는 것 같았고(?), Windows Form Control 은 ActiveX Control 을 작성하는 방법을 이미 알고 있었다. 그래서 WPF 로 작성한 Application 을 Control 로 조금 수정하고, 이를 Windows Form 형태의 Proxy Control (WPF Control 을 hosting 함)을 만들어서 ActiveX 컨트롤로 작성하기 위해서였다. 약간 트릭이긴 하지만... 그래도 이 방법이 시간과 비용을 절약하는 최선의 방법인것 같았다. |
Walkthrough: Hosting a Windows Forms Control in WPF
(http://msdn.microsoft.com/en-us/library/ms751761.aspx)
To host the MaskedTextBox control
1.Create a WPF Application project named HostingWfInWpf.
2.In Solution Explorer, add a reference to the WindowsFormsIntegration assembly, which is named WindowsFormsIntegration.dll.
3.In Solution Explorer, add a reference to the Windows Forms assembly, which is named System.Windows.Forms.dll.
4.Open Window1.xaml in the WPF Designer.
5.Replace the automatically generated XAML in Window1.xaml with the following XAML.
<Window x:Class="HostingWfInWpf.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="HostingWfInWpf" Loaded="WindowLoaded" > <Grid Name="grid1"> </Grid> </Window> |
6.In the Code Editor, open Window1.xaml.cs.
7.Replace the code in Window1.xaml.cs with the following code.
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Media; using System.Windows.Shapes; using System.Windows.Forms; namespace HostingWfInWpf { public partial class Window1 : Window { public Window1() { InitializeComponent(); } private void WindowLoaded(object sender, RoutedEventArgs e) { // Create the interop host control. System.Windows.Forms.Integration.WindowsFormsHost host = new System.Windows.Forms.Integration.WindowsFormsHost(); // Create the MaskedTextBox control. MaskedTextBox mtbDate = new MaskedTextBox("00/00/0000"); // Assign the MaskedTextBox control as the host control's child. host.Child = mtbDate; // Add the interop host control to the Grid // control's collection of child controls. this.grid1.Children.Add(host); } } } |
ElementHost Class
(http://msdn.microsoft.com/en-us/library/system.windows.forms.integration.elementhost.aspx)
A Windows Forms control that can be used to host a Windows Presentation Foundation (WPF) element.
Use the ElementHost control to place a WPF UIElement on your Windows Forms control or form. To host a Windows Forms control in a WPF element, use the WindowsFormsHost element.
|
To host a WPF element in a Windows Form, you must assign the WPF element to the Child property.
Use the PropertyMap property to assign custom mappings between an ElementHost control and its hosted WPF element. For more information, see Windows Forms and WPF Property Mapping.
private void Form1_Load(object sender, EventArgs e) { // Create the ElementHost control for hosting the // WPF UserControl. ElementHost host = new ElementHost(); host.Dock = DockStyle.Fill; // Create the WPF UserControl. HostingWpfUserControlInWf.UserControl1 uc = new HostingWpfUserControlInWf.UserControl1(); // Assign the WPF UserControl to the ElementHost control's // Child property. host.Child = uc; // Add the ElementHost control to the form's // collection of child controls. this.Controls.Add(host); } |
참고: Walkthrough: Hosting a WPF Control in Windows Forms (내용이 좀 길다)
(http://msdn.microsoft.com/en-us/library/ms742215.aspx)
How to register .NET components with COM

Building the project on a development machine
- Use: On a development machine
Registering by command, using the Regasm utility
- Use: When testing on a different machine and you do not have an installation program
- If the target machine has Visual Studio installed, open the Visual Studio 2005 command prompt (the ordinary command prompt will not have the appropriate environment variables set to use this tool).
- If the target machine does not have Visual Studio installed but does have the .NET Framework SDK installed, use the SDK command prompt by choosing Programs, then Microsoft .NET Framework SDK v2.0. If you cannot find it, open a command prompt at the path where Regasm is located. For example, the .NET Framework 2.0 default installation path is C:\Windows\Microsoft.NET\Framework\v2.0.50727.
Using an installation program
- Use: When deploying to your user
Type libraries for managed components
A type library (.tlb) can also be exported that contains information describing the types in the assembly. You may want to generate a type library for a component if that component will be used from another development environment, such as within the Visual Basic for Applications (VBA) environment embedded with the ArcGIS applications. If you want to add custom commands and tools using the Customize dialog box within the ArcGIS applications, you need to generate a type library.
http://edndoc.esri.com/arcobjects/9.2/NET/9826f81b-278c-49cc-a912-ab8d86f5e91e.htm
이중 인터페이스를 사용하는 형식에서는 클라이언트가 특정 인터페이스 레이아웃에 바인딩할 수 있습니다. 이후 버전에서 해당 형식이나 기본 형식의 레이아웃이 변경되면 인터페이스에 바인딩된 COM 클라이언트의 바인딩이 해제될 수 있습니다. 기본적으로 ClassInterfaceAttribute 특성이 지정되어 있지 않으면 디스패치 전용 인터페이스가 사용됩니다.
따로 표시되지 않은 경우 제네릭이 아닌 모든 public 형식은 COM에서 볼 수 있으며 public이 아닌 모든 제네릭 형식은 COM에서 볼 수 없습니다.
이 규칙 위반 문제를 해결하려면 ClassInterfaceAttribute 특성의 값을 None으 로 변경하고 인터페이스를 명시적으로 정의합니다.
다음 예제에서는 이 규칙을 위반하는 클래스와 명시적 인터페이스를 사용하도록 클래스를 다시 선언하는 방법을 보여 줍니다.
using System; using System.Runtime.InteropServices; [assembly: ComVisible(true)] namespace InteroperabilityLibrary { // This violates the rule. [ClassInterface(ClassInterfaceType.AutoDual)] public class DualInterface { public void SomeMethod() {} } public interface IExplicitInterface { void SomeMethod(); } [ClassInterface(ClassInterfaceType.None)] public class ExplicitInterface : IExplicitInterface { public void SomeMethod() {} } } |
출처 : http://msdn.microsoft.com/ko-kr/library/ms182205.aspx
From: http://www.c-sharpcorner.com/uploadfile/dsandor/activexinnet11102005040748am/activexinnet.aspx
소스는 원저작자가 만든 것:
테스트로 작성한 것 (ProgId, "ActiveXDotNet.myControl" 로 생성 가능)
Software developers have used ActiveX controls on their web pages to add advanced functionality to the web experience. With my migration from a Visual Basic 6 world to a Microsoft
In this example, I will walk you through creating an ActiveX control that will show a simple user interface and accept input from a web page. This process will involve the following steps:
- Create an assembly (class library project) that contains an item of type User Control.
- Expose an interface for the control.
- Embed the user control into a web page.
- Transfer
data from a web form to the control and display the data on the control.
Step 1: Create an assembly.
You can use the example provided for download, or simply create your own project from scratch. In this section I will outline everything you need to do in order to properly create your assembly.
First, you create a new project of type Class Library. Name the class library ActiveXDotNet.
Once the project is created, delete the Class1.cs file from your project as it will not be necessary. Next, add a User Control to the project by right clicking on the project in your solution explorer, choose Add, then User Control. Name your user control myControl.
On the user control, add some UI elements, and a text box control named txtUserText. The txtUserText control will display the user data that is typed into the web form. This will demonstrate how to pass data to your User Control.
When you are done adding your user interface to the control we now have to add a key element to the control, an Interface. The interface will allow COM/COM+ objects to know what properties they can use. In this case, we are going to expose one public property named UserText. That property will allow us to set the value of the text box control.
Step 2: Expose the Interface for the control.
First, create a private String to hold the data passed from the web form to the control:
private String mStr_UserText;
Place this String just inside the Class myControl.
Next, we will create a public property. The web page will use this property to pass text back to your control. This property will allow reading and writing of the value mStr_UserText.
public String UserText
{
get { return mStr_UserText; }
set
{
mStr_UserText = value;
//Update the text box control value also.
txtUserText.Text = value;
}
}
In this example, you will note the extra code in the set section of the public property. When a value is passed from the web form to the control we will set the private String value equal to the value passed to the property. In addition, we are simply going to modify the value of the Text Box control directly. Typically you would NOT do this. Instead, you would raise an event and then validate the data being passed by examining the private variable mStr_UserText. Then you would set the value of the Text Box Control. However, that would add significant code to this example and for simplicity sake I am omitting that security precaution.
Now that you have a public property that .NET assemblies can use, you need to make that property available to the COM world. We do this by creating an Interface and making the myControl class inherit the interface. This will allow COM objects to see what properties we have made available.
Your code will now look like this:
namespace ActiveXDotNet
{
public interface AxMyControl
{
String UserText { set; get ; }
}
public class myControl : System.Windows.Forms.UserControl, AxMyControl
{
private String mStr_UserText;
public String UserText
{
get { return mStr_UserText; }
set
{
mStr_UserText = value;
//Update the text box control value also.
txtUserText.Text = value;
}
}
...
Notice that we now have an interface defined, the interface tells COM/COM+ that there is a public property available for use that is of type String and is readable (get) and writeable (set). All we do now is have the Class myControl inherit the interface and viola! We have a .NET assembly that acts like an ActiveX Control.
Step 3: Embed the user control in a web page.
The last thing we do now is use the control in an example web page.
<html>
<body color=white>
<hr>
<font face=arial size=1>
<OBJECT id="myControl1" name="myControl1" classid="ActiveXDotNet.dll#ActiveXDotNet.myControl" width=288 height=72>
</OBJECT>
</font>
<form name="frm" id="frm">
<input type="text" name="txt" value="enter text here"><input type=button value="Click me" onClick="doScript();">
</form>
<hr>
</body>
<script language="javascript">
function doScript()
{
myControl1.UserText = frm.txt.value;
}
</script>
</html>
You will notice in the HTML code above, that you call your .NET assembly very similar to an ActiveX control; however there is no GUID, and no .OCX file. Your CLASSID is now the path to your DLL and the Namespace.Classname identifier. Refer to the code above to understand the syntax of the CLASSID object tag property. Place the HTML file and your DLL in the same directory on your web server and navigate to the HTML document. (Do not load the HTML document by double clicking on it, navigate to it in your browser by using the Fully Qualified URL.) *NOTE: You might need to add your web server to your Trusted Sites list in your Internet Explorer browser.
Step 4: Transfer data from the web form to the user control.
When you load the HTML page, your control should load into the page and you will see a web form with a text box and a button. In this example, if you type some text into the text box and click the button, it will use JavaScript to send the text from the web page form, to the User Control that you just built. Your User Control will then display the text in the Text Box control that I on the form.
Where do I go from here?
There are many issues that you should investigate in order to properly create User Controls that work on a web page. .NET Security plays a big part in what you can actually do within the confines of your code. You should also investigate code signing your control.
Additional Reference: Exposing Windows Forms Controls as ActiveX Controls
http://www.codeproject.com/KB/miscctrl/exposingdotnetcontrols.aspx
1. Delegate 정의 (변수 선언이 아님을 주의하자!)
delegate void VoidOperation(uint x); delegate double TwoLongsOp(long L1, long L2); delegate string GetAsString(); public delegate string GetAsString(); |
2. Delegate의 인스턴스 생성
static void Main(string[] args) { int X = 40; GetAsString FirstStringMethod = new GetAsString(X.ToString); // 메소드를 파라미터로 전달 Console.WriteLine("String is" + FirstStringMethod()); } |
- Delegate 는 형식 안전하므로 호출되는 메소드의 signature 가 제대로 되었다는 것이 보장된다.
- 메소드가 정적 메소드 혹은 인스턴스 메소드인지 신경쓰지 않는다.
+, -, -=, += 의 연산자를 이용하여 Delegate 를 추가/삭제 할 수 있으며, void 형으로 선언한다.
delegate void DoubleOp(double value); class MathOperations { public static void MultiplyByTwo(double value) { double result = value*2; Console.WriteLine("Multiplying by 2: {0} gives {1}", value, result); } public static void Squre(double value) { double result = value*value; Console.WriteLine("Squaring: {0} gives {1}", value, result); } } static void Main(string[] args) { DoubleOp operations = new DoubleOp(MathOperations.MultiplyByTwo); operations += new DoubleOp(MathOperations.Square); ProcessAndDisplayNumber(operations, 2.0); ProcessAndDisplayNumber(operations, 7.94); Console.WriteLine(); } |
참고 : Professional C# - 정보 문화사
A Simple C# Global Low Level Keyboard Hook

아래는 샘플 App 이미지와 Control 키 후킹을 테스트 해본 코드. 원본은 아래에 링크를 걸어 두었다.
http://www.codeproject.com/KB/cs/CSLLKeyboardHook.aspx