2010-07-06 18 views
6

CreateProcess जैसे फ़ंक्शंस को पॉइंटर्स लेने के लिए हस्ताक्षर करने वाले हस्ताक्षर होते हैं जो पॉइंटर्स को structs पर लेते हैं। सी में मैं स्टैक पर एक डमी स्ट्रक्चर ऑब्जेक्ट बनाने और डमी को पॉइंटर पास करने के बजाय वैकल्पिक पैरामीटर के लिए पॉइंटर के रूप में NULL पास कर दूंगा।पी/स्ट्रोक

सी # में, मैं के रूप में (पी/आह्वान)

[DllImport("kernel32.dll", CharSet = CharSet.Auto)] 
     public static extern bool CreateProcess(
      string lpApplicationName, 
      string lpCommandLine, 
      ref SECURITY_ATTRIBUTES lpProcessAttributes, 
      ref SECURITY_ATTRIBUTES lpThreadAttributes, 
      bool bInheritHandles, 
      CreateProcessFlags dwProcessCreationFlags, 
      IntPtr lpEnvironment, 
      string lpCurrentDirectory, 
      ref STARTUPINFO lpStartupInfo, 
      ref PROCESS_INFORMATION lpProcessInformation); 

यह घोषणा की है लेकिन अगर मैं lpProcessAttributes तर्क या lpThreadAttributes तर्क के लिए null पारित करने के लिए प्रयास करते हैं, मैं एक संकलक त्रुटि मिलती है:

Error 2 Argument 3: cannot convert from '<null>' to 'ref Debugging.Wrappers.SECURITY_ATTRIBUTES'

मैं उपरोक्त फ़ंक्शन हस्ताक्षर को कैसे संशोधित कर सकता हूं ताकि मैं इस कंपाइलर त्रुटि के बिना, SECURITY_ATTRIBUTES तर्कों के लिए null पास कर सकूं? (और यदि मैं चाहता हूं तो एक वास्तविक संरचना को पार करने में भी सक्षम हो सकता है?)

+0

ऐसा लगता है कि मेरा प्रश्न इस जैसा ही है, हालांकि मैं इसे शीर्षक से अनुमानित नहीं करता। http://stackoverflow.com/questions/1049623/how-to-pass-a-nullable-type-to-a-p-invoked- कार्यक्षमता –

उत्तर

3

null केवल संदर्भ प्रकारों के लिए मान्य है .Net। आपकी SECURITY_ATTRIBUTES एक struct है, जो ValueType है। शून्य से गुजरने के बजाय, आपको एक खाली सुरक्षा_एटीटीआरबीयूटीएस संरचना पारित करने की आवश्यकता है। (बस अपनी कॉल में new SECURITY_ATTRIBUTES()) कहें।

एक क्लीनर विधि अपने struct करने के लिए एक स्थिर खाली संपत्ति जोड़ने के लिए, और सिर्फ पारित SECURITY_ATTRIBUTES.Empty

[StructLayout(LayoutKind.Sequential)] 
public struct SECURITY_ATTRIBUTES { 
    public int nLength; 
    public IntPtr lpSecurityDescriptor; 
    public int bInheritHandle; 

    public static SECURITY_ATTRIBUTES Empty { 
     get { 
      return new SECURITY_ATTRIBUTES { 
       nLength = sizeof(int)*2 + IntPtr.Size, 
       lpSecurityDescriptor = IntPtr.Zero, 
       bInheritHandle = 0, 
      }; 
     } 
    } 
} 

या बेहतर अभी तक, बल्कि पी/आह्वान एक प्रक्रिया बनाने के लिए उपयोग करने की तुलना, System.Diagnostics.Process वर्ग की जाँच है, जो शायद आपको वह करना चाहिए जो आपको चाहिए। (!):

struct के बजाय वर्ग के रूप में SECURITY_ATTRIBUTES घोषित और रेफरी द्वारा इसे पारित नहीं है

+0

धन्यवाद, मुझे यह सुरक्षा_ATTRIBUTES.Empty पैटर्न पसंद है। –

+0

वैसे, मैं प्रक्रिया बनाने के लिए पी/इनवॉक का उपयोग कर रहा था क्योंकि मैं उन प्रक्रिया विशेषाधिकारों के साथ काम करना चाहता हूं जिन्हें प्रबंधित एपीआई द्वारा समर्थित नहीं किया जा रहा है। लेकिन अन्यथा हाँ, मैंने सिस्टम का उपयोग किया होगा। डायग्नोस्टिक्स.प्रोसेस क्लास। –

+0

लेकिन खाली संपत्ति के साथ समस्या यह है कि आप इसे रेफ पैरामीटर के रूप में पास नहीं कर सकते हैं। यह देखते हुए कि structs से निपटने वाले Win32 एपीआई के कई पते एक पते की अपेक्षा करते हैं, रेफरी की आवश्यकता है। – Adarsha

6

ठीक है, मैं अंत में ऐसा करने का एक और भी बेहतर रास्ता मिल गया। :-)

[DllImport("kernel32.dll", SetLastError = true)] 
    public static extern bool CreateProcess(
     string lpApplicationName, 
     StringBuilder lpCommandLine, 
     SECURITY_ATTRIBUTES lpProcessAttributes, 
     SECURITY_ATTRIBUTES lpThreadAttributes, 
     bool bInheritHandles, 
     CreateProcessFlags dwCreationFlags, 
     IntPtr lpEnvironment, 
     string lpCurrentDirectory, 
     STARTUPINFO lpStartupInfo, /// Required 
     PROCESS_INFORMATION lpProcessInformation //Returns information about the created process 
     ); 

/// <summary> 
/// See http://msdn.microsoft.com/en-us/library/aa379560(v=VS.85).aspx 
/// </summary> 
[StructLayout(LayoutKind.Sequential)] 
public class SECURITY_ATTRIBUTES 
{ 
    public uint nLength; 
    public IntPtr lpSecurityDescriptor; 
    [MarshalAs(UnmanagedType.Bool)] public bool bInheritHandle; 
} 

बोनस: यह भी आप जो nLength initializes SECURITY_ATTRIBUTES पर एक सभ्य निर्माता की घोषणा कर सकते हैं।

+0

यह कोई फर्क नहीं पड़ता कि आप कक्षा का नाम बदलते हैं। बहुत बढ़िया जवाब! –

+1

मुझे आश्चर्य है कि यह सुरक्षित है या नहीं। 'स्ट्रक्चरलाइट' विशेषता केवल वर्गों को प्रभावित कर सकती है, कक्षाओं में नहीं। तो शायद .NET की जेआईटी इस वर्ग में खेतों को किसी भी तरह से रख सकती है। उदाहरण के लिए, मुझे आश्चर्य है कि यह x64 या अन्य प्लेटफॉर्म पर असफल हो सकता है। मैं एक सुरक्षित चाल नहीं हो सकता है। –

+0

मैंने अभी एक एमएसएफटी आंतरिक सीएलआर विशेषज्ञ से सुना है कि यह एक सुरक्षित चाल है। :) –

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^