开发截屏软件的收获
开发截屏软件的收获:
1、可以使用System.Windows.Deployment.Current.Dispatcher.BeginInvoke(...)来在UI的Dispatcher上执行任务,而且避免引用Application,可以在类库中使用。
2、在普通.net中可以使用自定义SynchronizationContext子类进行任务调度,然后SynchronizationContext.SetSynchronizationContext设置当前的任务调度器、消息泵,但是在Silverlight中是不能调用SynchronizationContext.SetSynchronizationContext,因为SynchronizationContext.SetSynchronizationContext标记为 [SecurityCritical],标记为 [SecurityCritical]的都不能被UserCode调用。
为SynchronizationContext.Current.Post((obj) => { Capture(); }, null)来进行任务调用。
3、DllImport工具包:调用 Dehydrator.AllowMultitasking = true;启用多任务,启用以后DispatcherTimer停止了,但是可以在页面中通过BackgroundWorkder或者Thread启动后台线程,在后台线程中不断循环,这样退出后仍然可以继续运行。
4、DllImport工具包: Dispatcher.BeginInvoke是靠DispatcherTimer进行任务调度的。DispatcherTimer在应用到后台的时候是不触发Tick事件的、Webclient在应用到后台的时候是不启动异步请求的,虽然调用OpenWriteAsync不报错、Phone.KeyboardHook.StartHook音量键、拍照键都可以。
5、在非UI线程中不能new WritableBitmap,但是可以先在UI线程中new WritableBitmap,然后在线程中还可以操作它。
6、PC中调用Connectivity来操作设备、模拟器、部署应用等:
添加对C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.SmartDevice.Connectivity\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.SmartDevice.Connectivity.dll、C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualStudio.DeviceConnectivity.Interop.10.0\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.DeviceConnectivity.Interop.10.0.dll的引用。代码
internal static DeviceInfo[] GetDevices()
{
List<DeviceInfo> list = new List<DeviceInfo>();
DatastoreManager manager = new DatastoreManager(0x409);
foreach (Platform platform in manager.GetPlatforms())
{
foreach (Device device in platform.GetDevices())
{
list.Add(new DeviceInfo(platform.Id.ToString(), device.Id.ToString(), device.Name));
}
}
return list.ToArray();
}
var deviceInfo = GetDevices()[0];
DatastoreManager manager = new DatastoreManager(0x409);
Device device = manager.GetPlatform(new ObjectId(deviceInfo.PlatformId)).GetDevice(new ObjectId(deviceInfo.DeviceId));
device.Connect();
可以调用device的InstallAppllication等方法对手机进行操作。
尝试调用FileDeployer的方法在PC和手机之间进行文件传输:
var fieldmConmanServer= device.GetType().GetField("mConmanServer", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
var mConmanServer = fieldmConmanServer.GetValue(device);
Type typeFileDeployer = typeof(FileDeployer);
var constr = typeFileDeployer.GetConstructors(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)[0];
FileDeployer dep = (FileDeployer)constr.Invoke(new object[] { mConmanServer });
Guid appID = new Guid("{730189d4-189f-4238-a6d7-3d78a8680d1b}");
if (device.IsApplicationInstalled(appID))
{
string filename = @"\Applications\Data\" + appID + @"\Data\IsolatedStore\screen.jpg";
dep.SendFile("c:/boot.ini", @"\DOCFILE\a.txt");
dep.ReceiveFile(filename, @"screen.jpg");
//dynamic fileDep = new FileDeployer(mConmanServer);
MessageBox.Show("ok");
}
else
{
MessageBox.Show("notinstall");
}
但是调用失败,ReceiveFile、SendFile报错没有权限。
7、尝试调用Dispatcher的Dispatch干扰消息泵
//var d = Dispatcher;
////wp7中只能反射调用public成员
//var methodTimerTick = d.GetType().GetMethod("Dispatch", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
//methodTimerTick.Invoke(d, new object[] {8});
////d.TimerTick(null, null);
但是失败,因为WindowsPhone中的反射不能调用private成员。
8、Socket发送的时候不是Send(buffer,...)就都传出去了,因为并不是都会发出去,需要自己进行控制,Send的返回值是本次发送的数据量
void sendpost()
{
sockaddr_in serverAddr;
SOCKET sock;
hostent * host;
host = gethostbyname("192.168.1.100");
if(host==NULL)
{
return;
}
sock = socket(AF_INET, SOCK_STREAM,0);
serverAddr.sin_addr = *(struct in_addr*)host->h_addr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(9999);//25
if(connect(sock,(const sockaddr*)&serverAddr,sizeof(sockaddr))==SOCKET_ERROR)
{
int i = WSAGetLastError();
closesocket(sock);
return;
}
char buffer[1024];
sprintf(buffer,"POST /UploadScreenCapture.ashx HTTP/1.1\r\n");//from为char数据。存储发送地址
send(sock,buffer,strlen(buffer),0);
char *data = (char*)malloc(1024*1000*sizeof(char));//要发送的数据。
for(int i=0;i<sizeof(data)/sizeof(char);i++)
{
data[i] = 5;
}
sprintf(buffer,"Content-Length: %d\r\n\r\n",sizeof(data));//from为char数据。存储发送地址
send(sock,buffer,strlen(buffer),0);
int len = sizeof(data)/sizeof(char);
int res;
int pos = 0; //下一次发送需要开始的位置:
while(pos < len)
{
res = send(sock, data + pos , len - pos, 0);
if(res <=0)
break;
pos += res;
}
send(sock,data,sizeof(data),0);
//free(data);
closesocket(sock);
return;
}
9、WP7Network、DllImport等生成的dll一般都是为ARM真机编译的,如果要在模拟器上运行,需要用WinCE编译器编译成X86的dll因为模拟器是X86架构的。