2011-04-08 17 views
7

से पीडीएफ दस्तावेज कैसे मुद्रित करें मेरे पास विंडोज सेवा है जो समय-समय पर सर्वर से पीडीएफ दस्तावेज़ मुद्रित करनी चाहिए। मेरे समारोहविंडोज सेवा

private void PrintFormPdfData(byte[] formPdfData) 
{ 
    string tempFile; 

    tempFile = Path.GetTempFileName(); 

    using (FileStream fs = new FileStream(tempFile, FileMode.Create)) 
    { 
     fs.Write(formPdfData, 0, formPdfData.Length); 
     fs.Flush(); 
    } 

    string pdfArguments = string.Format("/p /h\"{0}\"", tempFile); 

    string pdfPrinterLocation = @"C:\Program Files (x86)\Adobe\Reader 9.0\Reader\AcroRd32.exe"; 


    ProcessStartInfo newProcess = new ProcessStartInfo(pdfPrinterLocation, pdfArguments); 
    newProcess.CreateNoWindow = true; 
    newProcess.RedirectStandardOutput = true; 
    newProcess.UseShellExecute = false; 
    newProcess.RedirectStandardError = true; 

    Process pdfProcess = new Process(); 
    pdfProcess.StartInfo = newProcess; 
    pdfProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 
    pdfProcess.Start(); 
    pdfProcess.WaitForExit(); 
} 

जब मैं विंडोज आवेदन यह काम करता है, लेकिन यह काम नहीं करता है जब मैं Windows सेवा में लागू में यह लागू है।

क्या आप मेरी मदद कर सकते हैं?

+0

क्या "काम नहीं करता"? क्या आपको कोई त्रुटि मिल रही है? –

उत्तर

10

मैं इस समस्या सत्र 0. साथ मैं अब इस वर्ग

public class ProcessStarter : IDisposable 
{ 
    #region Import Section 

    private static uint STANDARD_RIGHTS_REQUIRED = 0x000F0000; 
    private static uint STANDARD_RIGHTS_READ = 0x00020000; 
    private static uint TOKEN_ASSIGN_PRIMARY = 0x0001; 
    private static uint TOKEN_DUPLICATE = 0x0002; 
    private static uint TOKEN_IMPERSONATE = 0x0004; 
    private static uint TOKEN_QUERY = 0x0008; 
    private static uint TOKEN_QUERY_SOURCE = 0x0010; 
    private static uint TOKEN_ADJUST_PRIVILEGES = 0x0020; 
    private static uint TOKEN_ADJUST_GROUPS = 0x0040; 
    private static uint TOKEN_ADJUST_DEFAULT = 0x0080; 
    private static uint TOKEN_ADJUST_SESSIONID = 0x0100; 
    private static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY); 
    private static uint TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID); 

    private const uint NORMAL_PRIORITY_CLASS = 0x0020; 

    private const uint CREATE_UNICODE_ENVIRONMENT = 0x00000400; 


    private const uint MAX_PATH = 260; 

    private const uint CREATE_NO_WINDOW = 0x08000000; 

    private const uint INFINITE = 0xFFFFFFFF; 

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

    public enum SECURITY_IMPERSONATION_LEVEL 
    { 
     SecurityAnonymous, 
     SecurityIdentification, 
     SecurityImpersonation, 
     SecurityDelegation 
    } 

    public enum TOKEN_TYPE 
    { 
     TokenPrimary = 1, 
     TokenImpersonation 
    } 

    public enum WTS_CONNECTSTATE_CLASS 
    { 
     WTSActive, 
     WTSConnected, 
     WTSConnectQuery, 
     WTSShadow, 
     WTSDisconnected, 
     WTSIdle, 
     WTSListen, 
     WTSReset, 
     WTSDown, 
     WTSInit 
    } 

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
    public struct STARTUPINFO 
    { 
     public Int32 cb; 
     public string lpReserved; 
     public string lpDesktop; 
     public string lpTitle; 
     public Int32 dwX; 
     public Int32 dwY; 
     public Int32 dwXSize; 
     public Int32 dwYSize; 
     public Int32 dwXCountChars; 
     public Int32 dwYCountChars; 
     public Int32 dwFillAttribute; 
     public Int32 dwFlags; 
     public Int16 wShowWindow; 
     public Int16 cbReserved2; 
     public IntPtr lpReserved2; 
     public IntPtr hStdInput; 
     public IntPtr hStdOutput; 
     public IntPtr hStdError; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    internal struct PROCESS_INFORMATION 
    { 
     public IntPtr hProcess; 
     public IntPtr hThread; 
     public int dwProcessId; 
     public int dwThreadId; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    private struct WTS_SESSION_INFO 
    { 
     public Int32 SessionID; 

     [MarshalAs(UnmanagedType.LPStr)] 
     public String pWinStationName; 

     public WTS_CONNECTSTATE_CLASS State; 
    } 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    static extern uint WTSGetActiveConsoleSessionId(); 

    [DllImport("wtsapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    static extern bool WTSQueryUserToken(int sessionId, out IntPtr tokenHandle); 

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    public extern static bool DuplicateTokenEx(IntPtr existingToken, uint desiredAccess, IntPtr tokenAttributes, SECURITY_IMPERSONATION_LEVEL impersonationLevel, TOKEN_TYPE tokenType, out IntPtr newToken); 

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    static extern bool CreateProcessAsUser(IntPtr token, string applicationName, string commandLine, ref SECURITY_ATTRIBUTES processAttributes, ref SECURITY_ATTRIBUTES threadAttributes, bool inheritHandles, uint creationFlags, IntPtr environment, string currentDirectory, ref STARTUPINFO startupInfo, out PROCESS_INFORMATION processInformation); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    static extern bool CloseHandle(IntPtr handle); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    static extern int GetLastError(); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    static extern int WaitForSingleObject(IntPtr token, uint timeInterval); 

    [DllImport("wtsapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    static extern int WTSEnumerateSessions(System.IntPtr hServer, int Reserved, int Version, ref System.IntPtr ppSessionInfo, ref int pCount); 

    [DllImport("userenv.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit); 

    [DllImport("wtsapi32.dll", ExactSpelling = true, SetLastError = false)] 
    public static extern void WTSFreeMemory(IntPtr memory); 

    [DllImport("userenv.dll", SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool DestroyEnvironmentBlock(IntPtr lpEnvironment); 

    #endregion 

    /// <summary> 
    /// Initializes a new instance of the <see cref="ProcessStarter"/> class. 
    /// </summary> 
    public ProcessStarter() 
    { 

    } 

    /// <summary> 
    /// Initializes a new instance of the <see cref="ProcessStarter"/> class. 
    /// </summary> 
    /// <param name="processName">Name of the process.</param> 
    /// <param name="fullExeName">Full name of the exe.</param> 
    public ProcessStarter(string processName, string fullExeName) 
    { 
     processName_ = processName; 
     processPath_ = fullExeName; 
    } 

    /// <summary> 
    /// Initializes a new instance of the <see cref="ProcessStarter"/> class. 
    /// </summary> 
    /// <param name="processName">Name of the process.</param> 
    /// <param name="fullExeName">Full name of the exe.</param> 
    /// <param name="arguments">The arguments.</param> 
    public ProcessStarter(string processName, string fullExeName, string arguments) 
    { 
     processName_ = processName; 
     processPath_ = fullExeName; 
     arguments_ = arguments; 
    } 

    /// <summary> 
    /// Gets the current user token. 
    /// </summary> 
    /// <returns></returns> 
    public static IntPtr GetCurrentUserToken() 
    { 
     IntPtr currentToken = IntPtr.Zero; 
     IntPtr primaryToken = IntPtr.Zero; 
     IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero; 

     int dwSessionId = 0; 
     IntPtr hUserToken = IntPtr.Zero; 
     IntPtr hTokenDup = IntPtr.Zero; 

     IntPtr pSessionInfo = IntPtr.Zero; 
     int dwCount = 0; 

     WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, ref pSessionInfo, ref dwCount); 

     Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO)); 

     Int32 current = (int)pSessionInfo; 
     for (int i = 0; i < dwCount; i++) 
     { 
      WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO)); 
      if (WTS_CONNECTSTATE_CLASS.WTSActive == si.State) 
      { 
       dwSessionId = si.SessionID; 
       break; 
      } 

      current += dataSize; 
     } 

     WTSFreeMemory(pSessionInfo); 

     bool bRet = WTSQueryUserToken(dwSessionId, out currentToken); 
     if (bRet == false) 
     { 
      return IntPtr.Zero; 
     } 

     bRet = DuplicateTokenEx(currentToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenPrimary, out primaryToken); 
     if (bRet == false) 
     { 
      return IntPtr.Zero; 
     } 

     return primaryToken; 
    } 

    /// <summary> 
    /// Runs this instance. 
    /// </summary> 
    public void Run() 
    { 

     IntPtr primaryToken = GetCurrentUserToken(); 
     if (primaryToken == IntPtr.Zero) 
     { 
      return; 
     } 
     STARTUPINFO StartupInfo = new STARTUPINFO(); 
     processInfo_ = new PROCESS_INFORMATION(); 
     StartupInfo.cb = Marshal.SizeOf(StartupInfo); 

     SECURITY_ATTRIBUTES Security1 = new SECURITY_ATTRIBUTES(); 
     SECURITY_ATTRIBUTES Security2 = new SECURITY_ATTRIBUTES(); 

     string command = "\"" + processPath_ + "\""; 
     if ((arguments_ != null) && (arguments_.Length != 0)) 
     { 
      command += " " + arguments_; 
     } 

     IntPtr lpEnvironment = IntPtr.Zero; 
     bool resultEnv = CreateEnvironmentBlock(out lpEnvironment, primaryToken, false); 
     if (resultEnv != true) 
     { 
      int nError = GetLastError(); 
     } 

     CreateProcessAsUser(primaryToken, null, command, ref Security1, ref Security2, false, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, lpEnvironment, null, ref StartupInfo, out processInfo_); 

     DestroyEnvironmentBlock(lpEnvironment); 
     CloseHandle(primaryToken); 
    } 

    /// <summary> 
    /// Stops this instance. 
    /// </summary> 
    public void Stop() 
    { 
     Process[] processes = Process.GetProcesses(); 
     foreach (Process current in processes) 
     { 
      if (current.ProcessName == processName_) 
      { 
       current.Kill(); 
      } 
     } 
    } 

    /// <summary> 
    /// Waits for exit. 
    /// </summary> 
    /// <returns></returns> 
    public int WaitForExit() 
    { 
     WaitForSingleObject(processInfo_.hProcess, INFINITE); 
     int errorcode = GetLastError(); 
     return errorcode; 
    } 



    #region IDisposable Members 

    /// <summary> 
    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 
    /// </summary> 
    public void Dispose() 
    { 
    } 

    #endregion 

    private string processPath_ = string.Empty; 
    private string processName_ = string.Empty; 
    private string arguments_ = string.Empty; 
    private PROCESS_INFORMATION processInfo_; 

    /// <summary> 
    /// Gets or sets the process path. 
    /// </summary> 
    /// <value>The process path.</value> 
    public string ProcessPath 
    { 
     get 
     { 
      return processPath_; 
     } 
     set 
     { 
      processPath_ = value; 
     } 
    } 

    /// <summary> 
    /// Gets or sets the name of the process. 
    /// </summary> 
    /// <value>The name of the process.</value> 
    public string ProcessName 
    { 
     get 
     { 
      return processName_; 
     } 
     set 
     { 
      processName_ = value; 
     } 
    } 

    /// <summary> 
    /// Gets or sets the arguments. 
    /// </summary> 
    /// <value>The arguments.</value> 
    public string Arguments 
    { 
     get 
     { 
      return arguments_; 
     } 
     set 
     { 
      arguments_ = value; 
     } 
    } 
} 

का उपयोग का समाधान, जैसे मेरी समारोह देखो:

 private void PrintFormPdfData(byte[] formPdfData) 
    { 
     string tempFile; 

     tempFile = Path.GetTempFileName(); 

     using (FileStream fs = new FileStream(tempFile, FileMode.Create)) 
     { 
      fs.Write(formPdfData, 0, formPdfData.Length); 
      fs.Flush(); 
     } 
     string pdfArguments =string.Format("/t /o {0} \"Printer name\"", tempFile); 

     string pdfPrinterLocation = @"C:\Program Files (x86)\Adobe\Reader 9.0\Reader\AcroRd32.exe"; 

     try 
     { 

     ProcessStarter processStarter = new ProcessStarter("AcroRd32", pdfPrinterLocation, pdfArguments); 
     processStarter.Run(); 
     processStarter.WaitForExit(); 
     processStarter.Stop(); 

     } 
     finally 
     { 
      File.Delete(tempFile); 
     } 

} 

इसके अलावा, ServiceProcessInstaller खाता "स्थानीय सिस्टम" पर सेट होना आवश्यक है। जब मैंने सेवा बनाई, तो मैंने इस उपयोगकर्ता के साथ "स्थानीय सेवा" पर सेट किया, यह काम नहीं करता है। मैंने "नेटवर्क सेवा" या "उपयोगकर्ता"

1

आप ओएस का उल्लेख नहीं था, लेकिन मुझे लगता है आप Session 0 isolation विशेषता यह है कि Windows Vista में जोड़ा गया है में चल रहे हैं, सर्वर 2008 और बाद में ओएस रिलीज

आवेदन इस सुविधा से प्रभावित वर्गों में शामिल हैं:

सेवाएं जो यूआई बनाती हैं।

एक ऐसी सेवा जो एक संदेश के साथ संवाद करने के लिए SendMessage और PostMessage जैसे विंडो-संदेश फ़ंक्शंस का उपयोग करने का प्रयास करती है।

वैश्विक स्तर पर नामित वस्तुओं को बनाने वाले अनुप्रयोग।

+0

मैं वर्तमान में विंडोज 7 पर चल रहा हूं। लेकिन बाद में मुझे एक्सपी नड विंडोज 7 या विस्टा पर चलाने की आवश्यकता होगी। जब मैं इस फ़ंक्शन को चलाता या डिबग करता हूं तो मुझे कोई त्रुटि नहीं होती है। – cashmere

+0

हाँ, यह फेंक और त्रुटि नहीं करेगा लेकिन आप रनटाइम पर अपेक्षित परिणाम नहीं देखेंगे। हालांकि, क्या आपने Windows XP मशीन पर यह देखने के लिए प्रयास किया है कि प्रिंट वास्तव में काम करता है या नहीं, यह पुष्टि करेगा कि यह सत्र 0 चीज है, क्योंकि Windows XP में S0 अलगाव – kd7

+0

नहीं है, मैं सत्र 0 के साथ समस्या कैसे हल कर सकता हूं? – cashmere

1

"इस समस्या में पाया गया रजिस्ट्री संपादन के साथ इस समस्या को हल नहीं किया: https://support.microsoft.com/en-us/kb/184291

विंडोज सेवाओं (और आईआईएस) से प्रिंटिंग सिस्टम खाते का उपयोग करता है क्योंकि मैं इसे समझता हूं। इस खाते में प्रिंटर तक पहुंच नहीं है लेकिन ये रजिस्ट्री संपादन सिस्टम खाता प्रिंटिंग विशेषाधिकार देता है।

  1. निर्यात 3 कुंजी ("regedit.exe के भीतर फ़ोल्डर") फ़ाइलें .reg लिए:
    • HKEY_CURRENT_USER \ Software \ Microsoft \ Windows NT \ वर्तमान वर्शन \ डिवाइस

      यहाँ एक सारांश है

    • HKEY_CURRENT_USER \ Software \ Microsoft \ Windows NT \ वर्तमान वर्शन \ PrinterPorts
    • HKEY_CURRENT_USER \ Software \ Microsoft \ Windows NT \ वर्तमान वर्शन \ Windows
  2. संपादित अपने 3 नव निर्मित reg फ़ाइलें और परिवर्तन "HKEY_CURRENT_USER" से "HKEY_USERS \ .DEFAULT"
  3. डबल उन्हें एक्सप्लोरर में क्लिक करके अपने 3 reg फ़ाइलें चलाने (यह उन्हें रजिस्ट्री करने के लिए कहते हैं)

यह सब कुछ लेता है। इससे मुझे आईआईएस 7 में PHP से प्रिंटर में पीडीएफ फाइलों को मुद्रित करने में मदद मिली। मेरी PHP स्क्रिप्ट तब तक ठीक काम करेगी जब सर्वर को स्क्रिप्ट चलाने पर प्रशासक लॉग इन हुआ था।अब कोई भी में लॉग इन करने की जरूरत है और स्क्रिप्ट अभी भी काम करता है :)

मुझे आशा है कि यह किसी के रूप में ज्यादा खोज और संवारता के रूप में मैं में डाल यह पता लगाने के लिए बचाता है।