//获取dll的绝对路径,请根据不同情况自己选用
MessageBox.Show(System.Reflection.Assembly.GetExecutingAssembly().Location);
MessageBox.Show(System.Reflection.Assembly.GetEntryAssembly().Location);
MessageBox.Show(System.Windows.Forms.Application.ExecutablePath);
MessageBox.Show(System.Windows.Forms.Application.StartupPath);
MessageBox.Show(System.Environment.CurrentDirectory);
MessageBox.Show(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
C#枚举窗口句柄
在CS程序中启动其他应用后,要获取进程的主窗体其实很简单:
Process p = Process.Start(exePath);
//p.WaitForInputIdle();
p.Refresh();
IntPtr mainWnd = p.MainWindowHandle;
但是,总有很多特殊的情况,上面的方法根本无法用,所以,要用Windows API来搞定了
1、如果窗口信息很固定而且没有重名的话,可以用Findwindow搞定
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
IntPtr clientWnd = FindWindow(null,"FormClient");
2、根据标题枚举窗口句柄
//枚举窗体
[DllImport("User32.dll", EntryPoint = "EnumWindows", SetLastError = true)]
public static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, uint lParam);
//获取窗体标题
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpText, int nCount);
//设置错误状态
[DllImport("kernel32.dll", EntryPoint = "SetLastError")]
public static extern void SetLastError(uint dwErrCode);
//线程主窗口句柄
private static IntPtr processMainWnd = IntPtr.Zero;
//要查找的窗口名称
private static String winTitle = "__Web__Form__Main__";
//声明委托函数
public delegate bool WNDENUMPROC(IntPtr hwnd, uint lParam);
//枚举进程句柄,非线程安全
[SecuritySafeCritical]
public static IntPtr GetCurrentWindowHandle()
{
IntPtr ptrWnd = IntPtr.Zero;
bool bResult = EnumWindows(new WNDENUMPROC(EnumWindowsProc), (uint)0);
if (!bResult && Marshal.GetLastWin32Error() == 0)
{
ptrWnd = processMainWnd;
}
return ptrWnd;
}
//枚举函数,获取主窗口句柄然后退出
[SecuritySafeCritical]
private static bool EnumWindowsProc(IntPtr hwnd, uint lParam)
{
//根据标题获取窗体
var sb = new StringBuilder(50);
GetWindowText(hwnd, sb, sb.Capacity);
if (winTitle.Equals(sb.ToString()))
{
processMainWnd = hwnd;
SetLastError(0);
return false;
}
return true;
}
3、跟进进程id枚举获取主窗体句柄
//枚举窗体
[DllImport("User32.dll", EntryPoint = "EnumWindows", SetLastError = true)]
//获取父窗体
[DllImport("user32.dll", EntryPoint = "GetParent", SetLastError = true)]
//根据窗口获取线程句柄
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowThreadProcessId(IntPtr hwnd, out uint pid);
//设置错误状态
[DllImport("kernel32.dll", EntryPoint = "SetLastError")]
public static extern void SetLastError(uint dwErrCode);
//线程主窗口句柄
private static IntPtr processMainWnd = IntPtr.Zero;
//枚举进程句柄
[SecuritySafeCritical]
public static IntPtr GetCurrentWindowHandle(int processId)
{
IntPtr ptrWnd = IntPtr.Zero;
bool bResult = EnumWindows(new WNDENUMPROC(EnumWindowsProc), (uint)processId);
if (!bResult && Marshal.GetLastWin32Error() == 0)
{
ptrWnd = processMainWnd;
}
return ptrWnd;
}
//枚举函数,获取主窗口句柄然后退出
[SecuritySafeCritical]
private static bool EnumWindowsProc(IntPtr hwnd, uint lParam)
{
uint uiPid = 0;
//根据启动方式不同,这里要有相应修改
if (GetParent(hwnd) == IntPtr.Zero)
{
GetWindowThreadProcessId(hwnd, out uiPid);
if (uiPid == lParam)
{
processMainWnd = hwnd;
SetLastError(0);
return false;
}
}
}
4、跟进窗口WindowsClassName举获取主窗体句柄
//查找桌面
[DllImport("User32.dll", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
public static extern IntPtr GetDesktopWindow();
//获取窗体句柄
[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern IntPtr GetWindow(IntPtr hwnd, int wFlag);
//获取窗体类
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
public const int GW_CHILD = 5;
public const int GW_HWNDNEXT = 2;
//枚举桌面窗口,根据WindowsClassName获取句柄
[SecuritySafeCritical]
public static IntPtr GetWinHandleByClasName(String windowClassNmae)
{
//取得桌面窗口,再获取第一个子窗口
IntPtr hwnd = GetDesktopWindow();
hwnd = GetWindow((IntPtr)hwnd, System.Convert.ToInt32(GW_CHILD));
//通过循环来枚举所有的子窗口
while ((long)hwnd != 0)
{
System.Text.StringBuilder ClassName = new System.Text.StringBuilder(256);
GetClassName((IntPtr)hwnd, ClassName, ClassName.Capacity);
String tmpClassName= ClassName.ToString().Trim();
if (tmpClassName.Length > 0)
{
if (tmpClassName.Equals(windowClassNmae))
{
break;
}
}
hwnd = GetWindow((IntPtr)hwnd, System.Convert.ToInt32(GW_HWNDNEXT));
}
return hwnd;
}
使用WebBrower修改网页iFrame中的内容
由于很变态的中国式需求,我们需要在自己的网站中,嵌入第三方厂商的网站。
而这个第三方的网站中,使用了几层的iFrame,同时使用了基于IE的Activex控件。
由于双方的控件风格差距太大,所以需要替换CSS样式,同时要删掉部分与我们网站冲突的内容。
想了几种方法:
1、说服对方进行调整,但经过接触,了解到其超级不靠谱,只能靠自己了。
2、直接通过iFrame嵌入对方网站,用JS进行修改。可是跨站修改,浏览器不同意啊。
3、自己写个控件,嵌入到自己网页中,在控件中调用对方URL,并通过WebBrowser控件修改CSS及HTML。问题是,IE中,不能再直接嵌入一个WebBrowser控件,主要出于安全考虑。(如果IE允许这样操作的话,我只需要在WebBrowser中指向同一个URL,就可以无限调用,耗光资源,其他的事情,有太多可以做了)自己用很挫的方法实现了这个功能,后来考虑到稳定性,放弃了。
4、使用非基于IE的Web插件,在控件中调用对方URL,并通过控件修改CSS及HTML。比如Flash或者CefSharp,但问题是,非IE核心如何调用Activex控件啊。
5、限制入口,基于WebBrowser定制IE浏览器
最后使用了方法5,说实话,真烦。
这里把通过WebBrowser修改CSS及HTML的方法说一下,下面是我写的一段测试用代码,请按自己的实际情况修改:
//替换样式
//webMain是WebBrowser控件的名称
//NewStyle.css中是要替换的样式
private void modifyStyle()
{
int frameNum = webMain.Document.Window.Frames.Count;
if (frameNum == 2)
{
IHTMLDocument2 leftIFrame = webMain.Document.Window.Frames[0].Document.DomDocument as IHTMLDocument2;
int length = leftIFrame.styleSheets.length;
IHTMLStyleSheet styleSheet = leftIFrame.createStyleSheet(@"", length + 1);
TextReader reader = new StreamReader(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "NewStyle.css"));
string style = reader.ReadToEnd();
styleSheet.cssText = style;
}
}
//删除tree节点下的div,只保留特定的一个节点
private void delDiv(String flowid)
{
int frameNum = webMain.Document.Window.Frames.Count;
if (frameNum == 2)
{
IHTMLDocument3 leftIFrame = webMain.Document.Window.Frames[0].Document.DomDocument as IHTMLDocument3;
foreach (dynamic e in leftIFrame.getElementById("tree").children)
{
String ret = e.InnerText;
if (!ret.Contains(flowid))
{
e.parentNode.removeChild(e);
}
}
}
}
我可怜的Nexus7平板啊
想来Nexus7已经挂了4、5个月了吧,今年我的电子产品挂得真是干脆,各种悲剧啊。
其实起因很简单,我从广州回上海时,没有带Nexus7。
当我重新回到广州后,发现没什么电了,但可以更新,于是点击了更新。
更新后,无论如何,Nexus7都会卡在Google的启动界面。
当时心情正郁闷而且Nexus7很久没有Root过了,于是准备开始Root。
网上下了最新的Root工具,然后开始Root。
但过了好久都没有任何反应。
立即清楚,这次悲剧了。
重启后,发现Bootloader已经没有了。
网上各种查找资料,发现Nexus7的1代,这个问题我不是第一个遇到,但大家的解决方法,都是“返厂”。
老子代购的,怎么“返厂”啊。
于是在广州、上海找了不少人帮忙看,发现,我的刷机水平,比他们中95%的人都强。
要是能进入fastboot,我找你干吗?
后来,有人说刷字库可以解决问题,找了两家试试,甚至发快递到深圳修,发现都搞不定。
唉。。。
非主流的悲剧啊。。。
估计是没什么希望了。。。
刷机有风险,入行需谨慎。。。
如何在WinForm程序中测试C#写的COM控件
在网上查了一下,应该是不能直接在WinForm中使用C#写的COM控件。
但可以用变通的方法测试COM控件中的方法,比如,下面的例子中,就可以测试addTest方法:
Type comType = null;
object comObject = null;
//这个无效,不知道为什么
//comType = Type.GetTypeFromProgID("XX.CSControl.TestControl");
if (comType == null)
{
Guid guid = new Guid("4B4D1D4C-16CA-48E0-87A4-AFF3C6CB6E26");
comType = Type.GetTypeFromCLSID(guid);
}
try
{
comObject = Activator.CreateInstance(comType);
}
catch(Exception e)
{
MessageBox.Show(e.Message);
return;
}
object[] args = new object[2];
args[0] = 1;
args[1] = 2;
int ret = (int)comType.InvokeMember("addTest", BindingFlags.InvokeMethod, null, comObject, args);
if(ret==3)
{
MessageBox.Show("TestOK");
}
C#开发COM组件(Web)
这两天由于一个很挫的需求,准备开发一个COM组件,由于所有用户的客户端都安装有.Net Framework 4.0,加上工期紧的很,就准备用C#上了。
1、首先,建立一个Windows Forms Control Library项目
2、项目属性,Build,选中,Register for COM interop
3、项目属性,Signing,选中,Sign the assembly,并生成一个签名文件
4、编辑AssemblyInfo.cs,查看是否有下面两行,没有要添加
using System.Security; [assembly: AllowPartiallyTrustedCallers()] [assembly: ComVisible(true)]
5、添加接口文件IObjectSafety.cs
using System;
using System.Runtime.InteropServices;
namespace CSControl
{
//不要修改GUID
[ComImport]
[Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
[PreserveSig]
int GetInterfaceSafetyOptions(ref Guid riid,
[MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions,
[MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);
[PreserveSig()]
int SetInterfaceSafetyOptions(ref Guid riid,
[MarshalAs(UnmanagedType.U4)] int dwOptionSetMask,
[MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
}
}
6、控件类要同时实现UserControl, IObjectSafety两个接口
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.Security;
namespace CSControl
{
//更改为你自己的UUID
[ComVisible(true)]
[Guid("4B4D1D4C-16CA-48E0-87A4-AFF3C6CB6E26")]
[ProgId("XX.CSControl.TestControl")]
public partial class TestControl : UserControl, IObjectSafety
{
//===================================================
//实现IObjectSafety接口
//不要修改下面的GUID
private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}";
private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
private const int S_OK = 0;
private const int E_FAIL = unchecked((int)0x80004005);
private const int E_NOINTERFACE = unchecked((int)0x80004002);
private bool _fSafeForScripting = true;
private bool _fSafeForInitializing = true;
public int GetInterfaceSafetyOptions(ref Guid riid,
ref int pdwSupportedOptions,
ref int pdwEnabledOptions)
{
int Rslt = E_FAIL;
string strGUID = riid.ToString("B");
pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
switch (strGUID)
{
case _IID_IDispatch:
case _IID_IDispatchEx:
Rslt = S_OK;
pdwEnabledOptions = 0;
if (_fSafeForScripting == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
Rslt = S_OK;
pdwEnabledOptions = 0;
if (_fSafeForInitializing == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
break;
default:
Rslt = E_NOINTERFACE;
break;
}
return Rslt;
}
public int SetInterfaceSafetyOptions(ref Guid riid,
int dwOptionSetMask,
int dwEnabledOptions)
{
int Rslt = E_FAIL;
string strGUID = riid.ToString("B");
switch (strGUID)
{
case _IID_IDispatch:
case _IID_IDispatchEx:
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) &&
(_fSafeForScripting == true))
Rslt = S_OK;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) &&
(_fSafeForInitializing == true))
Rslt = S_OK;
break;
default:
Rslt = E_NOINTERFACE;
break;
}
return Rslt;
}
//===================================================
//实现UserControl接口
......
}
}
7、编译,控件会自动注册
8、写个网页,测试一下
<!--CSControl--> <object id="testControl" width="500" height="500" classid ="clsid:4B4D1D4C-16CA-48E0-87A4-AFF3C6CB6E26"]</object>
9、打CAB包,发布到网站
由于是自己生产的签名文件,所以会有安全提示。最简单的方法是从靠谱的CA那里买一个证书,还有办法就是将证书导入到IE的信任列表中,再就是将IE的安全级别降为最低。
10、当然也可以通过命令行本地注册
rem 注册 regtlibv12 %PATH_TO_DLL_AND_TLB_FOLDER%\CSControl.tlb rem 反注册 regtlibv12 -u %PATH_TO_DLL_AND_TLB_FOLDER%\CSControl.tlb
C#开发COM组件(本地)
本篇文章介绍了如何用C#写一个简单的COM组件(Dll)。
1、新建一个C# Class Library项目“CSCOMTest”
2、项目中,新增一个接口文件IJustATestCOM.cs,Guid要自己生成
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace CSCOMTest
{
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("A5377871-3334-4679-A3CD-84312B1DCD3E")]
public interface IJustATestCOM
{
int Add(int a, int b);
String SayHiTo(String someOne);
}
}
3、项目中,新增一个类文件JustATestCOM.cs,Guid要自己生成
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace CSCOMTest
{
[ComVisible(true)]
[Guid("A6E4F456-32C1-4C8E-9171-D616B5DA1E20")]
[ProgId("CSCOMTest.JustATestCOM")]
public class JustATestCOM : IJustATestCOM
{
public int Add(int a, int b)
{
return a + b;
}
public String SayHiTo(String someOne)
{
return "Hi " + someOne + "!";
}
}
}
4、项目属性->Application->Assembly Infomation->Make Assembly COM-Visible->打勾
5、项目属性->Signing->Sign the assembly->打勾
项目属性->Signing->Choose a strong name key file->New
6、编译
7、注册
#这里一定要用正确版本的gacutil及RegAsm C:\VBS\DNFW4\gacutil.exe /i CSCOMTest.dll C:\VBS\DNFW4\RegAsm.exe CSCOMTest.dll
8、反注册
#这里一定要用正确版本的gacutil及RegAsm C:\VBS\DNFW4\gacutil.exe /u CSCOMTest C:\VBS\DNFW4\RegAsm.exe /u CSCOMTest.dll
9、调用测试
'发生错误时,继续运行
On Error Resume Next
'清除错误状态
Err.Clear
Set Obj=CreateObject("CSCOMTest.JustATestCOM")
'输出错误信息
If Err.Number <> 0 Then
WScript.Echo "Error: " & Err.Number
WScript.Echo "Error (Hex): " & Hex(Err.Number)
WScript.Echo "Source: " & Err.Source
WScript.Echo "Description: " & Err.Description
'Err.Clear
'退出程序
WScript.Quit(Err.Number)
End If
'On Error Goto 0
WScript.Echo obj.Add(1,2)
WScript.Echo obj.SayHiTo("dcom")
set obj=Nothing
10、生成tlb文件
regasm CSCOMTest.dll /tlb:CSCOMTest.tlb
iPhone4数据备份成功
//=========================================================
上周在天津,找了个iPhone的修理店,里面的小师傅说我的iPhone4主板短路了,不能修。
我和他们商量,帮我换块电池吧,结果被一大三小四个师傅一起鄙视,说是会引起火灾。
估计到最后他们也没明白,我只是想备份数据,手机不打算用了。
但人家说就是不可能开机了,靠,鄙视,有电明明能开机的。
没办法,自己X宝买了个电池。
//=========================================================
昨天,终于回到上海。
电池早就到了,于是下班的时候,换上新电池,开始了手机数据备份。。。
换了电池,开机,成功了!
哈哈哈哈哈。。。
马上备份。。。
然后手机开始发烫,关到飞行模式也不行。。。
只好备份一部分就关机散热,中途自己一顿人工降温。。。
弄了半个小时,终于备份完成了。。。
//=========================================================
后记:
昨天晚上去买5S,晚上去中山公园的永乐买,结果没32G的,就跑到了陆家嘴Apple旗舰店。
买是买到了,但发现,卡必须是nano的,没有卡没法激活。
靠。。。
再等等吧。。。
//=========================================================
卡激活了,还是去联通剪的卡,还在下雨,好坑的说
终于用上了:)
//=========================================================
鄙视Apple,刚买了不到一个月,降价了1200,一张机票没了:(
获取Eclipse执行文件根目录
Eclipse插件获取Eclipse的根目录
String eclipseRoot = Platform.getInstallLocation().getURL().toString();
eclipseRoot = eclipseRoot.replace("file:/", "");
Eclipse插件获取Workspace根目录
//方法1
String workspaceRoot= Platform.getInstanceLocation().getURL().toString();
workspaceRoot = workspaceRoot.replace("file:/", "");
//方法2
String path = Activator.getDefault().getStateLocation().makeAbsolute().toFile().getAbsolutePath();
Eclipse插件获取User根目录
String userHome = Platform.getUserLocation().getURL().toString();
userHome = userHome.replace("file:/", "");
Elclipse插件获取Bundle的OSGI路径
//方法1
String bundlePath = Activator.getDefault().getBundle().getLocation();
String pathBundle = bundlePath.replace("reference:file:/","");
//方法2
Bundle bundle = Platform.getBundle("bundle id");
URL urlentry = bundle.getEntry("bundle resource path");
String strEntry = FileLocator.toFileURL(urlentry).getPath();
//方法3
String pathClass = KeyHandler.class.getResource("resource path").getFile();
Java获取当前虚拟机32位还是64位
Java获取当前虚拟机32位还是64位:
String archdatamodel = System.getProperty("sun.arch.data.model");
if (archdatamodel.equals("32")) {
//32
} else {
//64
}
Java获取当前虚拟机架构:
String arch = System.getProperty("os.arch");
if (arch.equals("x86")) {
//x86
} else {
//amd64
}