在windows环境下,qt从mtp设备中获取文件

您所在的位置:网站首页 usb设备实例路径怎么修改文件 在windows环境下,qt从mtp设备中获取文件

在windows环境下,qt从mtp设备中获取文件

2024-07-15 18:40| 来源: 网络整理| 查看: 265

需求描述 1.在window环境下 2.使用qt 3.从mtp设备中获取文件。

很显然这么奇葩的需求,肯定不是我自己想做的,没错的,你猜对了。是一个项目的需求。首先分析这个需求,我认为最难的一点就是基于window来做。(当然那些专业搞c#的人,整天研究大微软的人例外)。这个东西放在linux下简直太easy了。正因为在window下来做,所以难点就来了:首先你需要能获取到mtp设备下的文件,你要明白mtp设备是没有盘符的,这就意味着你指望qt中的方法调用肯定是没法实现了,所以这就成为了第一个难点,第二个难点:就是你得集成进qt里边去。当然这个第二个难点取决于你是怎么来解决第一个难点的。下面我就来说说我是如何一步一步干掉这些个问题的。

1.第一个坑:从mtp设备中获取文件 1.1 第一个大坑中的第一个小坑:采取何种方式获取mtp设备中的文件。

首先,必须得着手解决掉这个问题,于是我开始我的万里长征第一步,开始漫无目的的查资料。其实在网上翻过一遍之后,方法无非就是俩种:一种就是微软的那一套,直接去调用微软的API,各种C#,不过我一想到VISUAL STUDIO安装包就是几个G,而且作为一个平时只使用Ubuntu的码农来说,这种方法一开始在我的脑海中就被毙掉了。第二种就是基于libusb实现的libmtp。说实话,我一开始的时候计划按照这种方法来做的,不过资料全是基于linux的,我再看这个资料的过程中,无意中发现了一个从来没有听说过的东西Powershell. 一看到这个神奇的东西中带了shell,我就心里莫名的开心,因为我知道它和linux中的shell肯定多多少少会有联系。只要有联系,让我去搞这个东西,我就有把握。果断决定采取powershell这种方法。 powershell这种东西就是微软搞得一套自己的shell.(个人感觉是因为微软自己感觉Linux的shell太好用了,所以眼红了,就模仿人家搞了一套,不过我想说微软的这个powershell简直就是辣鸡!!!)。而且有一点很重要win7之后的windows都内置了powershell。看到这一点我就决定了要用这一套,因为它在windows上起码不用做多余的配置。

1.2 第一个大坑中的第二个小坑:利用Powershell去复制mtp设备中的文件。

写到这儿,(我必须吐槽一下:windows的powershell.既然你要模仿,你就给我好好地模仿…)作为一个习惯穿梭在linux下shell脚本的码农来说,powershell的语法我用晦涩难懂,简直就是辣鸡,来形容一点儿也不为过。接下来进入正题吧,下面是我调试通的从mtp设备中拷贝文件的shell脚本代码。

function Get-ShellProxy { if( -not $global:ShellProxy) { $global:ShellProxy = new-object -com Shell.Application } $global:ShellProxy } function Get-ShellItem { param($Path=17) $shell=Get-ShellProxy trap [System.Management.Automation.MethodInvocationException] { $Path = $Path.ToString() $dir = $Path.Substring( 0 ,$Path.LastIndexOf('\') ) return $shell.NameSpace($dir).items() | where { (-not $_.IsFolder ) -and $_.path -eq $Path} | select -First 1 continue } $shell.NameSpace($Path).self } function Get-ChildShellItem { param( $Path=17, [switch]$Recurse, $Filter=$null) Filter myFilter { if($Filter){ $_ | where { $_.Name -match $Filter } } else{ $_ } } $shellItem = Get-ShellItem $Path $shellItem | myFilter if( $shellItem.IsFolder ){ if($Recurse) { $shellItem | myFilter $stack=New-Object System.Collections.Stack $stack.Push($shellItem) while($stack.Count -gt 0) { $top = $stack.Pop() $top | myFilter $top.GetFolder.items() | foreach { if( $_.IsFolder ) { $stack.Push($_) } else { $_ | myFilter } } } } else{ $shellItem.GetFolder.items() | myFilter } } } function Copy-ShellItem { param($Path,$Destination) $shell=Get-ShellProxy $shell.NameSpace($Destination).Copyhere($Path,16) } $des = '你需要拷贝到PC中的位置' $phone = Get-ChildShellItem | where { $_.name -eq '你的设备名称' } Get-ChildShellItem -Path "$($phone.Path)\sdcard" -Filter '(.json)|(.js)$' | foreach { echo $_ Copy-ShellItem -Path $_ -Destination $des } 第二个坑:集成进qt中

当我成功的跳过第一个坑之后,在powershell中执行完脚本之后,看到文件成功复制到了我pc上的文件夹之后,别提我有多高兴了。根据我对linux调用脚本的easy程度,我以为在windos进行集成也很容易。结果我又一次的错了。第二个坑丝毫不亚于第一个坑。我只能硬着头皮开始了跨越第二坑的过程。

2.1第二个坑中的第一个小坑:采用何种方法进行集成

我开始了各种尝试在qt中去运行powershell脚本,不料我认为我都能用的方法,结果调试都没通了。最后的最后,想了一个大招,因为知道,exe可执行文件是可以在qt中被跑起来的,所以我就想到把脚本编成可执行文件的形式(其实这一步走弯路了,不过实在是没有办法)。下面是我调试可用的powershell脚本是用来生成可执行文件的。

function Convert-PS1ToExe { param( [Parameter(Mandatory=$true)] [ValidateScript({$true})] [ValidateNotNullOrEmpty()] [IO.FileInfo]$ScriptFile ) if( -not $ScriptFile.Exists) { Write-Warning "$ScriptFile not exits." return } [string]$csharpCode = @' using System; using System.IO; using System.Reflection; using System.Diagnostics; namespace LoadXmlTestConsole { public class ConsoleWriter { private static void Proc_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) { Process pro = sender as Process; Console.WriteLine(e.Data); } static void Main(string[] args) { // Set title of console Console.Title = "Powered by PSTips.Net"; // read script from resource Assembly ase = Assembly.GetExecutingAssembly(); string scriptName = ase.GetManifestResourceNames()[0]; string scriptContent = string.Empty; using (Stream stream = ase.GetManifestResourceStream(scriptName)) using (StreamReader reader = new StreamReader(stream)) { scriptContent = reader.ReadToEnd(); } string scriptFile = Environment.ExpandEnvironmentVariables(string.Format("%temp%\\{0}", scriptName)); try { // output script file to temp path File.WriteAllText(scriptFile, scriptContent); ProcessStartInfo proInfo = new ProcessStartInfo(); proInfo.FileName = "PowerShell.exe"; proInfo.CreateNoWindow = true; proInfo.RedirectStandardOutput = true; proInfo.UseShellExecute = false; proInfo.Arguments = string.Format(" -File {0}",scriptFile); var proc = Process.Start(proInfo); proc.OutputDataReceived += Proc_OutputDataReceived; proc.BeginOutputReadLine(); proc.WaitForExit(); Console.WriteLine("Hit any key to continue..."); Console.ReadKey(); } catch (Exception ex) { Console.WriteLine("Hit Exception: {0}", ex.Message); } finally { // delete temp file if (File.Exists(scriptFile)) { File.Delete(scriptFile); } } } } } '@ # $providerDict $providerDict = New-Object 'System.Collections.Generic.Dictionary[[string],[string]]' $providerDict.Add('CompilerVersion','v4.0') $codeCompiler = [Microsoft.CSharp.CSharpCodeProvider]$providerDict # Create the optional compiler parameters $compilerParameters = New-Object 'System.CodeDom.Compiler.CompilerParameters' $compilerParameters.GenerateExecutable = $true $compilerParameters.GenerateInMemory = $true $compilerParameters.WarningLevel = 3 $compilerParameters.TreatWarningsAsErrors = $false $compilerParameters.CompilerOptions = '/optimize' $outputExe = Join-Path $ScriptFile.Directory "$($ScriptFile.BaseName).exe" $compilerParameters.OutputAssembly = $outputExe $compilerParameters.EmbeddedResources.Add($ScriptFile.FullName) > $null $compilerParameters.ReferencedAssemblies.Add( [System.Diagnostics.Process].Assembly.Location ) > $null # Compile Assembly $compilerResult = $codeCompiler.CompileAssemblyFromSource($compilerParameters,$csharpCode) # Print compiler errors if($compilerResult.Errors.HasErrors) { Write-Host 'Compile faield. See error message as below:' -ForegroundColor Red $compilerResult.Errors | foreach { Write-Warning ('{0},[{1},{2}],{3}' -f $_.ErrorNumber,$_.Line,$_.Column,$_.ErrorText ) } } else { Write-Host 'Compile succeed.' -ForegroundColor Green "Output executable file to '$outputExe'" } }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3