2014-09-22 48 views
2

我使用的示例代碼創建在VB.Net的ActiveX - 埃克COM服務器:外的PROC埃克服務器

http://code.msdn.microsoft.com/windowsapps/VBExeCOMServer-74ecdb1c

當我打電話GetCurrentProcessID從Active-X-內Exe,它會返回與調用應用程序相同的ID。

有人可以告訴我,如果這是很自然的,或者我是否在封裝ActiveX-Exe組件時做了錯誤?

我這樣的測試它:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 

    _MouseIndicator = New twsMouseIndicator.clsMouseIndicator 
    With _MouseIndicator 
     .ImagePath = "d:\dev\projects\osc\gui\autoclick\prog4.png" 
     .Size = 300 
     .Alpha = 155 
     .FollowMouse = True 
     .Active = True 
    End With 

    Dim iProcessIDOutOfProcID As Integer = _MouseIndicator.CurrentProcessID 
    Dim iCallerProcessID As Integer = GetCurrentProcessId() 

    If iProcessIDOutOfProcID = iCallerProcessID Then 
     MessageBox.Show("ProcIDs are the same, namely " & iCallerProcessID & ". This can not be right!") 
    Else 
     MessageBox.Show("Everything is okay.") 
    End If 

End Sub 

在調用應用程序 「GetCurrentProcessID」 被聲明爲

Module Module1 
    ''' <summary> 
    ''' Get current process ID. 
    ''' </summary> 
    ''' <returns></returns> 
    <DllImport("kernel32.dll")> _ 
    Public Function GetCurrentProcessId() As UInt32 
    End Function 

End Module 

在亂PROC-COM-服務器,現宣佈像這樣:

Public Function CurrentProcessID() As UInt32 

    Return NativeMethod.GetCurrentProcessId 

End Function 

Friend Class NativeMethod 

    ''' <summary> 
    ''' Get current process ID. 
    ''' </summary> 
    ''' <returns></returns> 
    <DllImport("kernel32.dll")> _ 
    Friend Shared Function GetCurrentProcessId() As UInt32 
    End Function 
+0

你調用'GetCurrentProcessID'而不是'GetCurrentProcess'? – 2014-09-22 23:15:12

+0

@ 500-InternalServerError是。朋友共享函數GetCurrentProcessId()作爲UInt32 – tmighty 2014-09-23 06:54:44

+1

您可能需要顯示您添加的代碼以顯示進程ID以及如何比較它們,因爲它*適用於我的系統* http://i.imgur.com/5fO51vz.png – Plutonix 2014-09-25 02:13:05

回答

2

我發現了一個適用於我的開發環境的解決方案。我從註釋中引用的here中摘取了OP的示例項目。我已經創建了一個新的outofproc.zip,我希望爲OP工作。以下是我沿途發現和學習的一些歷史記錄。

我重建了VBExeComServer項目(它安裝並註冊了COM可執行文件)。我嘗試使用OP的caller項目,並通過CreateObject("VBExeCOMServer.SimpleObject")實例化SimpleObject的方法,並且它以與評論中描述的OP相同的方式掛起。我發現令人困惑。

然後我決定更仔細地看看VBExeComServer項目。這與OP在他的問題中發佈的樣本基本相同。由於這個項目已知工作,這可能是環境問題。經過一些試驗和錯誤,以及一些谷歌搜索,我發現這question on StackOverflow。雖然這個問題沒有得到答案,但我認爲提供的信息似乎與我所經歷的有些相似。特別是它說:

我想讓COM啓動我的進程外的.NET COM服務器。它的工作原理,如果服務器進程使用x64編譯,但如果我用AnyCPU(這是我想要的),那麼它掛起了一陣,並最終失敗0x80080005(CO_E_SERVER_EXEC_FAILURE)。我怎樣才能使這個工作?

我發現hangs for a while評論與我們所看到的非常相似。當我嘗試使用Powershell實例化對象時,我遇到了同樣的錯誤。雖然跡象表明他沒有得到它的工作,我覺得有足夠的調查我們的項目的設置。首先關閉VBExeComServer使用任何CPU作爲平臺類型。鑑於上面的摘錄,我決定通過配置管理器修改創建'x64'和'x86'平臺選項的項目。然後,我嘗試構建x64未能註冊可執行文件並構建類型庫。我試過x86並編譯/註冊。我發現這Microsoft Article關於x64組件,讓我在正確的軌道上。特別是它有這些指令:

要解決此問題,請使用以下步驟添加一個後期構建命令以調用RegAsm.exe的64位版本。

  1. 項目屬性,選擇「生成事件...」從編譯
  2. 添加以下後生成的命令行 「%WINDIR%\ Microsoft.NET \ Framework64 \ V2.0.50727 \ regasm」 「$(TARGETPATH)」

我沒有用什麼他們建議,因爲它會限制該項目只能建設64個。我決定通過查看構建平臺類型來增強這個想法。如果是x64,我將使用上面的Framework64 regasm。不幸的是,VBExeComServer項目(由MS製作)默認採用32位程序集而不是64位,因爲他們在後期構建事件中使用32位regasm。我結束了使用此爲post-build events

echo Generate and register type library. 
if "$(PlatformName)" == "x64" (
    C:\Windows\Microsoft.NET\Framework64\v2.0.50727\regasm.exe /tlb "$(TargetPath)" 
) else (
    C:\Windows\Microsoft.NET\Framework\v2.0.50727\regasm.exe /tlb "$(TargetPath)" 
) 
echo Register the component. 
if "$(PlatformName)" == "x64" (
    C:\Windows\Microsoft.NET\Framework64\v2.0.50727\regasm.exe "$(TargetPath)" 
) else (
    C:\Windows\Microsoft.NET\Framework\v2.0.50727\regasm.exe "$(TargetPath)" 
) 
echo Generate and register type library. 

我又試圖建設平臺Any CPU,並編譯和正確註冊。然後我做了x86,然後x64構建。他們都按預期構建和註冊。請注意,在構建COM服務器時,我運行Visual Studio爲管理員,以便COM註冊過程具有更新註冊表系統範圍的適當權限。

接下來我進入任務管理器(這很重要)。我殺掉了可能一直在鋪設的所有舊的VBExeComServer進程。人們可以求助於重新啓動窗口來確保。未能從內存中清理舊的可執行文件可能會導致未定義的行爲。

那麼現在caller(客戶端)代碼的工作?我加載了這個項目並且運行良好。我甚至修改了caller項目,建造爲x86x64Any CPU平臺,他們的工作。他們都發現SimpleObjectprocessid與客戶端進程不相同。

特別提醒:如果你想caller項目工作,在64位系統上使用的平臺類型Any CPU,或使用平臺類型x64你需要確保你建立一個64位VBExeComServer如上。不這樣做會導致我們經歷的掛起。

接下來,我恢復了OP的早期綁定代碼:

Private _Com As VBExeCOMServer.SimpleObject 
_Com = New VBExeCOMServer.SimpleObject 

我有預感,這將不加載通過COM /互操作的出的進程內的服務器。我是對的。當我恢復這些行時,我能夠運行caller程序,但Process IDs是相同的。原因是VB.Net COM對象是作爲一個程序集創建的,它恰好提供了一個進程外COM服務器。但是,如果您嘗試將EXE作爲引用(或TLB)導入,它會告訴您不能這樣做,因爲它是CLR程序集。當你做_Com As VBExeCOMServer.SimpleObject VB。Net將繞過所有COM/Interop代碼,並將該可執行文件作爲程序集直接訪問對象。

其他人可能有一個想法如何使這個工作的另一種方式。以下用途後期綁定

Private _Com As Object 
_Com = CreateObject("VBExeCOMServer.SimpleObject") 

CreateObject力量創造VBExeCOMServer.SimpleObject通過COM /互操作。如果它尚未運行,我們的COM服務器將會啓動。一旦服務器運行來處理我們的請求,將會實例化新的SimpleObject

我之前引用的我的outofproc.zip文件已經修改了上面提到的所有項目。至少在我的環境中,它確實按預期工作。

+1

哦,哇,多麼神奇的描述,謝謝!您的解決方案適用於我的系統,我很高興您發現後期綁定是唯一的解決方案,我永遠不會想到這一點。 – tmighty 2014-10-02 10:51:06

+0

Downvoter care提供一些信息來改善答案? – 2014-10-05 17:25:17