Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Как в VFP узнать информацию о файле (вкладка Summary) ? / 16 сообщений из 16, страница 1 из 1
03.11.2008, 22:58
    #35632863
Игорь2004
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
Как в VFP узнать информацию о файле, содержащуюся во вкладке Summary.
Правый щелчок мышью на файле, в появившемся меню выбрать Propereties,
вкладка Summary, Advanced , в появившемся окне можно увидеть много разной информации.
Меня, в частности интересует "Revision Number" ?
Второй вопрос, как можно конвертировать "Revision Number" в PackageCode, который в частности содержится в системном реестре, если речь идет об установочных пакетах *.msi ?
...
Рейтинг: 0 / 0
04.11.2008, 09:06
    #35633030
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
Игорь2004Как в VFP узнать информацию о файле, содержащуюся во вкладке Summary.
AGETFILEVERSION(ArrayName, cFileName)
...
Рейтинг: 0 / 0
04.11.2008, 16:47
    #35633568
Игорь2004
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
to Dima
прежде чем давать "ответ", Вы могли бы ознакомиться с описанием функции AGETFILEVERSION( ).
Мой вопрос требует знаний эксперта по FoxPro, ответ, скорее всего отрицательный, просто мне нужно было подтверждение перед тем, как я начну писать данную функцию, код на C у меня есть, его нужно переделать под стандарт fll библиотеки FoxPro.
...
Рейтинг: 0 / 0
04.11.2008, 19:52
    #35633770
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
Игорь2004to Dima
прежде чем давать "ответ", Вы могли бы ознакомиться с описанием функции AGETFILEVERSION( ).

Спасибо за душевный ответ ;)

Английской винды нет, наверно не совсем понял что тебе надо. AGETFILEVERSION( ) возвращает то что на вкладке "Версия" в свойствах показывается. Если не подходит - юзай WinAPI, других вариантов нет.
...
Рейтинг: 0 / 0
13.11.2008, 00:14
    #35650472
Игорь2004
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
Вот что у меня получилось, функция работает с установочными *.msi пакетами, а также с *.doc, *.xls документами возможно с другими типами файлов также.
Мне это нужно в основном для того, чтобы узнавать Revision Number msi пакета.
Критические конструктивные замечания приветствуются.
fll файл прикреплен
Примеры вызовов функции:
Код: plaintext
1.
2.
3.
4.
SET LIBRARY TO Agetfilesummary
 ?AGETFILESUMMARY("Afilesummary", _samples+"WebServices\Northwind\NorthwindWebservice_Setup.msi")
 Display Memory Like Afilesummary
 ?Agetfilesummary("Afilesummary", Getfile("doc,xls"))
 Display Memory Like Afilesummary
код на C
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
// the code from http://support.microsoft.com/kb/ 186898 /en-us
// has been adapted for VFP fll library by Igor Nikiforov  2008 - 11 - 12 
// Creates an array containing information about files with summary resources 
// or about Compound Document Properties 
// Return Value
// Numeric. AGETFILESUMMARY( ) returns the number of elements in the array. 
// If any error occurs AGETFILESUMMARY( ) returns the error code.
// If the file you specify does not exist or does not contain summary resources,
// AGETFILESUMMARY( ) returns zero, and the array, if already created, remains unchanged.
// AGETFILESUMMARY(ArrayName, cFileName)
// ArrayName Specifies the name of the array in which the file information is placed. 
// cFileName Specifies the name, and optionally the path, of the target file.
// Note:
// If an array or variable with name ArrayName already exists,
// the array or a variable will be deleted and the new array will be created.
// The function will produce an error if ArrayName already existed as a Public variable or array.
// This is because the function can only release a private variable or array and when an attempt
// to create the new array is executed a "variable already exists" error will occur. 
// Therefore, It is recommended that the SYS( 2015 ) function be used to obtain a unique name
// for the array to be created.
// The resulting array can then be loaded into a table or copied to a local array then deleted.
// The array created will have the following structure: 
// Column  1  property's name, type Character
// Column 2 property's value type Character, Numeric, Date etc
// Column  3  .F. for built-in  property and .T. for Custom's property, type Logical
// Column 4 windows property's type such as  VT_ARRAY, VT_BLOB etc., type Character
// Error codes:
//   STG_E_FILENOTFOUND      - 2147287038  File not found
//   STG_E_FILEALREADYEXISTS - 2147286960  Not a compound file
// Example
// ?AGETFILESUMMARY("Afilesummary", _samples+"WebServices\Northwind\NorthwindWebservice_Setup.msi")
// Display Memory Like Afilesummary
// ?Agetfilesummary("Afilesummary", Getfile("doc,xls"))
// Display Memory Like Afilesummary


#define  VISUAL_STUDIO_DOT_NET   0   // to compile in Visual Stidio .Net VISUAL_STUDIO_DOT_NET must be  1 

#include <pro_ext.h>
#include <stdio.h>
#include <windows.h>
#include <ole2.h>
#include <locale.h>



#define   MAXALLOCMEMORY	   1024 	 
typedef unsigned short USHORT;


/**************************************************************
Create a ASCIIZ sting from Value passed parameter
***************************************************************/
void FAR NullTerminate(Value FAR *cVal)  {
	if (!_SetHandSize(cVal->ev_handle, cVal->ev_length +  1 ))
		_Error( 182 ); // "Insufficient memory"
	_HLock(cVal->ev_handle);
	((char FAR *) _HandToPtr(cVal->ev_handle))[cVal->ev_length] = '\0';
	_HUnLock(cVal->ev_handle);
}


void makecolumn(Locator FAR *ploc, Value FAR * pv, char FAR * ps, int ncol) {
	ploc->l_sub2 = ncol;
	pv->ev_type = 'C';
	pv->ev_length = _StrLen(ps);
	_MemMove(_HandToPtr(pv->ev_handle), ps, pv->ev_length);
	_Store(ploc, pv);
}

void makenumcolumn(Locator FAR *ploc, Value FAR * pv) {
	ploc->l_sub2 =  2 ;
	pv->ev_type = 'N';
	pv->ev_width =  20 ;
	pv->ev_length  =  4 ;
	_Store(ploc, pv);
}


void makeintcolumn(Locator FAR *ploc, Value FAR * pv) {
	ploc->l_sub2 =  2 ;
	pv->ev_type = 'I';
	pv->ev_width =  12 ;
	_Store(ploc, pv);
}

// Dumps simple PROPVARIANT values.
void DumpPropVariant(PROPVARIANT *pPropVar, Locator FAR *ploc, Value FAR * pv) {
	char * ps;

	if(pPropVar->vt & VT_ARRAY) { // Don't iterate arrays, just inform as an array.
		// _PutStr("(Array)\n");
		ploc->l_sub2 = 2;
		_Store(ploc, pv);
		ps = "VT_ARRAY";
		makecolumn(ploc, pv, ps, 4) ;
		return;
	}
	
	if(pPropVar->vt & VT_BYREF) {  	// Don't handle byref for simplicity, just inform byref.
		// _PutStr("(ByRef)\n");
		ploc->l_sub2 =  2 ;
		_Store(ploc, pv);
		ps = "VT_BYREF";
		makecolumn(ploc, pv, ps,  4 ) ;
		return;
	}
	
	// Switch types.
	switch(pPropVar->vt) {
	case VT_EMPTY:
		// _PutStr("(VT_EMPTY)\n");
		ploc->l_sub2 =  2 ;
		_Store(ploc, pv);
		ps = "VT_EMPTY";
		makecolumn(ploc, pv, ps,  4 ) ;
		break;
	case VT_NULL:
		// _PutStr("(VT_NULL)\n");
		ploc->l_sub2 =  2 ;
		_Store(ploc, pv);
		ps = "VT_NULL";
		makecolumn(ploc, pv, ps,  4 ) ;
		break;
	case VT_BLOB:
		//_PutStr("(VT_BLOB)\n");
		ploc->l_sub2 =  2 ;
		_Store(ploc, pv);
		ps = "VT_BLOB";
		makecolumn(ploc, pv, ps,  4 ) ;
		break;
	case VT_BOOL:
		// _PutStr(pPropVar->boolVal ? "(VT_BOOL) TRUE/YES" : " (VT_BOOL) FALSE/NO");
		ploc->l_sub2 =  2 ;
		if (pPropVar->boolVal)
			pv->ev_length =  1 ;
		_Store(ploc, pv);
		ps = "VT_BOOL";
		makecolumn(ploc, pv, ps,  4 ) ;	
		break;
	case VT_I2: //  2 -byte signed int.
		// printf("%d (VT_I2)\n", (int)pPropVar->iVal);
		// PutNumLong((int)pPropVar->iVal);
		pv->ev_long  = (int)pPropVar->iVal;
		makeintcolumn(ploc, pv) ;
		ps = "VT_I2";
		makecolumn(ploc, pv, ps,  4 ) ;
		break;
	case VT_I4: //  4 -byte signed int.
		// printf("%d (VT_I4)\n", (int)pPropVar->lVal);
		// PutNumLong(pPropVar->iVal);
		pv->ev_long  = (int)pPropVar->lVal;
		makeintcolumn(ploc, pv) ;
		ps = "VT_I4";
		makecolumn(ploc, pv, ps,  4 ) ;
		break;
	case VT_R4: //  4 -byte real.
		// printf("%.2lf (VT_R4)\n", (double)pPropVar->fltVal);
		pv->ev_real   = (double)pPropVar->fltVal;
		makenumcolumn(ploc, pv) ;
		
		ps = "VT_R4";
		makecolumn(ploc, pv, ps,  4 ) ;
		break;
	case VT_R8: //  8 -byte real.
		// printf("%.2lf (VT_R8)\n", (double)pPropVar->dblVal);
		pv->ev_real   = (double)pPropVar->dblVal;
		makenumcolumn(ploc, pv) ;
		
		ps = "VT_R8";
		makecolumn(ploc, pv, ps,  4 ) ;
		break;
	case VT_BSTR: // OLE Automation string.
		{
			// Translate into ASCII.
			char dbcs[MAXALLOCMEMORY];
			char *pbstr = (char *)pPropVar->bstrVal;
#if VISUAL_STUDIO_DOT_NET
			size_t i ;
			wcstombs_s(&i, dbcs, MAXALLOCMEMORY, pPropVar->bstrVal,	*((DWORD *)(pbstr- 4 )));
#else
			int i = wcstombs(dbcs, pPropVar->bstrVal, *((DWORD *)(pbstr- 4 )));
#endif	
			dbcs[i] =  0 ;
			// printf("%s (VT_BSTR)\n", dbcs);
			ps = "VT_BSTR";
			makecolumn(ploc, pv, ps,  4 ) ;
			ps = dbcs;
			makecolumn(ploc, pv, ps,  2 ) ;
		}
		break;
	case VT_LPSTR: // Null-terminated string.
		{
			//	_PutStr(pPropVar->pszVal);
			ps = "VT_LPSTR";
			makecolumn(ploc, pv, ps,  4 ) ;
			ps = pPropVar->pszVal;
			makecolumn(ploc, pv, ps,  2 ) ;
		}
		break;
	case VT_FILETIME:
		{
			FILETIME lft;
			FileTimeToLocalFileTime(&pPropVar->filetime, &lft);  
			SYSTEMTIME lst;
			FileTimeToSystemTime(&lft, &lst);
			ps = (char FAR *)_HandToPtr(pv->ev_handle);
			ploc->l_sub2 =  2 ;
			sprintf(ps, "{^%d-%02d-%02d %02d:%02d.%02d}\0", lst.wYear, lst.wMonth, lst.wDay, lst.wHour, lst.wMinute, lst.wSecond);
			
			Value  TmpVal ;
			if ( _Evaluate(&TmpVal, ps)== 0 ) {
				_Store(ploc, &TmpVal);
			}
			else {
				sprintf(ps, "%02d:%02d.%02d %s %02d/%02d/%d\0",
					 1 +(lst.wHour- 1 )% 12 , lst.wMinute, lst.wSecond,
					(lst.wHour>= 12 ) ? "pm" : "am",
					lst.wMonth, lst.wDay, lst.wYear);
				pv->ev_type = 'C';
				pv->ev_length = _StrLen(ps);
				_Store(ploc, pv);
			}
			ps = "VT_FILETIME";
			makecolumn(ploc, pv, ps,  4 ) ;
		}
		break;
	case VT_CF: // Clipboard format.
		ploc->l_sub2 =  2 ;
		_Store(ploc, pv);
		ps = "VT_CF";
		makecolumn(ploc, pv, ps,  4 ) ;
		break;
	default: // Unhandled type, consult wtypes.h's VARENUM structure.
		// printf("(Unhandled type: 0x%08lx)\n", pPropVar->vt);
		ploc->l_sub2 = 2;
		_Store(ploc, pv);
		ps = "Unhandled type";
		makecolumn(ploc, pv, ps, 4) ;
		break;
	}
}

// Dump's built-in properties of a property storage.
unsigned long DumpBuiltInProps(IPropertySetStorage *pPropSetStg, Locator FAR *ploc) {
	IPropertyStorage *pPropStg = NULL;
	HRESULT hr;
	
	// Open summary information, getting an IpropertyStorage.
	hr = pPropSetStg->Open(FMTID_SummaryInformation, STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStg);
	
	if(FAILED(hr)) {
		return  0 ; 		// "No Summary-Information."
	}
	
	// Array of PIDSI's you are interested in.
	struct pidsiStruct {
		char *name;
		long pidsi;
	} pidsiArr[] = {
		{"Title",            PIDSI_TITLE}, // VT_LPSTR
		{"Subject",          PIDSI_SUBJECT}, // ...
		{"Author",           PIDSI_AUTHOR},
		{"Keywords",         PIDSI_KEYWORDS},
		{"Comments",         PIDSI_COMMENTS},
		{"Template",         PIDSI_TEMPLATE},
		{"LastAuthor",       PIDSI_LASTAUTHOR},
		{"Revision Number",  PIDSI_REVNUMBER},
		{"Edit Time",        PIDSI_EDITTIME}, // VT_FILENAME (UTC)
		{"Last printed",     PIDSI_LASTPRINTED}, // ...
		{"Created",          PIDSI_CREATE_DTM},
		{"Last Saved",       PIDSI_LASTSAVE_DTM},
		{"Page Count",       PIDSI_PAGECOUNT}, // VT_I4
		{"Word Count",       PIDSI_WORDCOUNT}, // ...
		{"Char Count",       PIDSI_CHARCOUNT},
		{"Thumpnail",        PIDSI_THUMBNAIL}, // VT_CF
		{"AppName",          PIDSI_APPNAME}, // VT_LPSTR
		{"Doc Security",     PIDSI_DOC_SECURITY}, // VT_I4
		{0, 0}
	};
	// Count elements in pidsiArr.
	int nPidsi = 0;
	for(nPidsi=0; pidsiArr[nPidsi].name; nPidsi++);
	
	// Initialize PROPSPEC for the properties you want.
	PROPSPEC *pPropSpec = new PROPSPEC [nPidsi];
	PROPVARIANT *pPropVar = new PROPVARIANT [nPidsi];
	
	for(int i=0; i<nPidsi; i++) {
		ZeroMemory(&pPropSpec[i], sizeof(PROPSPEC));
		pPropSpec[i].ulKind = PRSPEC_PROPID;
		pPropSpec[i].propid = pidsiArr[i].pidsi;
	}
	
	
	// Read properties.
	hr = pPropStg->ReadMultiple(nPidsi, pPropSpec, pPropVar);
	
	if(FAILED(hr)) {
		return 0;  		// "IPropertyStg::ReadMultiple() failed"
	}
	else {
		if (ploc) {
			Value v;
			if ((v.ev_handle = _AllocHand(MAXALLOCMEMORY)) == 0)
				_Error(182); // "Insufficient memory"
			
			_HLock(v.ev_handle);
			
			for(int i=0; i<nPidsi; i++) {
				ploc->l_sub1 = i+1;
				for ( ploc->l_sub2 = 1; ploc->l_sub2 <= 4; ploc->l_sub2++) {
					v.ev_type = 'C';
					switch (ploc->l_sub2) {
					case 1 :
						v.ev_length  = _StrLen(pidsiArr[i].name) ;
						_MemMove(_HandToPtr(v.ev_handle), pidsiArr[i].name, v.ev_length);
						_Store(ploc, &v);
						break;
					case 3 :
						v.ev_type = 'L';
						v.ev_length  = 0;
						_Store(ploc, &v);
						break;
					default:
						break;
					}
				}
				DumpPropVariant(pPropVar + i, ploc, &v);
			} 
			
			_HUnLock(v.ev_handle);
			_FreeHand(v.ev_handle);
		}
	}
	
	// De-allocate memory.
	delete [] pPropVar;
	delete [] pPropSpec;
	
	// Release obtained interface.
	pPropStg->Release();
	
	return (unsigned long) nPidsi;
}

// Dump's custom properties of a property storage.
unsigned long DumpCustomProps(IPropertySetStorage *pPropSetStg,	 Locator *ploc, unsigned long lasrrowcounforCustomProps) {
	Value v;
	unsigned long j= 0 ;
	
	IPropertyStorage *pPropStg = NULL;
	HRESULT hr;
	IEnumSTATPROPSTG *pEnumProp;
	
	// Open User-Defined-Properties, getting an IpropertyStorage.
	hr = pPropSetStg->Open(FMTID_UserDefinedProperties,	STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStg);
	if(FAILED(hr)) {
		return  0 ; // "No User Defined Properties."
	}
	
	hr = pPropStg->Enum(&pEnumProp); // Get property enumerator.
	if(FAILED(hr)) {
		pPropStg->Release();
		return  0 ;  // "Couldn't enumerate custom properties."
	}
	
	// Enumerate properties.
	STATPROPSTG sps;
	ULONG fetched;
	PROPSPEC propSpec[1];
	PROPVARIANT propVar[1];
	
	
	if (ploc) {
		if ((v.ev_handle = _AllocHand(MAXALLOCMEMORY)) == 0)
			_Error(182); // "Insufficient memory"
		_HLock(v.ev_handle);
	}
	
	while(pEnumProp->Next(1, &sps, &fetched) == S_OK) {
		// Build a PROPSPEC for this property.
		ZeroMemory(&propSpec[0], sizeof(PROPSPEC));
		propSpec[0].ulKind = PRSPEC_PROPID;
		propSpec[0].propid = sps.propid;
		
		hr = pPropStg->ReadMultiple(1, &propSpec[0], &propVar[0]); // Read this property.
		
		if(!FAILED(hr)) {
			j++;
			
			if (ploc) {  
				// Translate Prop name into ASCII.
				char dbcs[MAXALLOCMEMORY];
				char *pbstr = (char *)sps.lpwstrName;
#if VISUAL_STUDIO_DOT_NET
				size_t i ;
				wcstombs_s(&i, dbcs, MAXALLOCMEMORY, sps.lpwstrName,	*((DWORD *)(pbstr-4)));
#else
				int i = wcstombs(dbcs, sps.lpwstrName,	*((DWORD *)(pbstr-4)));
#endif
				dbcs[i] = 0;
				ploc->l_sub1 = (USHORT)(lasrrowcounforCustomProps+j);
				
				for ( ploc->l_sub2 = 1; ploc->l_sub2 <= 4; ploc->l_sub2++) {
					v.ev_type = 'C';
					switch (ploc->l_sub2) {
					case 1 :
						v.ev_length  = _StrLen(dbcs) ;
						_MemMove(_HandToPtr(v.ev_handle), dbcs, v.ev_length);
						_Store(ploc, &v);
						break;
					case 3 :
						v.ev_type = 'L';
						v.ev_length  = 1; // this is custom's property
						_Store(ploc, &v);
						break;
					default:
						break;
					}
					
				}
				// Dump this property.
				DumpPropVariant(&propVar[0], ploc, &v);
			}
		}
	}
	
	if (ploc) {
		_HUnLock(v.ev_handle);
		_FreeHand(v.ev_handle);
	}
	// Release obtained interface.
	pEnumProp->Release();
	pPropStg->Release();
	
	return j;
}


void FAR agetfilesummary(ParamBlk FAR *parm ) { // Creates an array containing information about files with Windows summary resources 
	unsigned long rowcount = 0, lasrrowcounforCustomProps = 0;
	char FAR *varName;
	Locator loc;
	int errcode ;
	NTI nti;
	char FAR *filename;
	WCHAR wcFilename[MAXALLOCMEMORY];
	int i;
	
	NullTerminate(&parm->p[1].val);     // Convert to ASCIIZ
	_HLock(parm->p[1].val.ev_handle);
	
	filename = (char FAR *) _HandToPtr(parm->p[1].val.ev_handle);
	// Dump's custom and built-in properties of a compound document.
	setlocale( LC_ALL, "" );
	i = mbstowcs(wcFilename, filename, _StrLen(filename)); // Translate filename to Unicode.
	_HUnLock(parm->p[1].val.ev_handle);
	
	setlocale( LC_ALL, "C" );
	wcFilename[i] = 0;
	
	IStorage *pStorage = NULL;
	IPropertySetStorage *pPropSetStg = NULL;
	HRESULT hr;
	
	// Open the document as an OLE compound document.
	hr = ::StgOpenStorage(wcFilename, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pStorage);
	
	if(FAILED(hr)) {
		/*
		if(hr == STG_E_FILENOTFOUND) 			// _UserError("File not found.");
			;
		else if(hr == STG_E_FILEALREADYEXISTS)  // _UserError("Not a compound file.");
			;
		else 	// _UserError("StgOpenStorage() failed ");
			;
        */
		_RetInt(hr, 20);
		return;
	}
	
	// Obtain the IPropertySetStorage interface.
	hr = pStorage->QueryInterface( IID_IPropertySetStorage, (void **)&pPropSetStg);
	
	if(FAILED(hr)) {  // "QI for IPropertySetStorage failed "
		pStorage->Release();
		_RetInt(hr, 20);
		return;
	}
	
	// Dump properties.
	lasrrowcounforCustomProps = rowcount = DumpBuiltInProps(pPropSetStg, (Locator FAR *)NULL);
	rowcount = rowcount + DumpCustomProps(pPropSetStg, (Locator FAR *)NULL, 0L);
	
	
	if (rowcount) {
		NullTerminate(&parm->p[0].val);     // Convert to ASCIIZ
		_HLock(parm->p[0].val.ev_handle);
		varName = (char FAR *) _HandToPtr(parm->p[0].val.ev_handle);
		
		// delete the array or a variable if they earlier existed
		if ((nti = _NameTableIndex(varName)) > -1) {
			if (_FindVar(nti, -1, &loc)) 
				if ((errcode =_Release(nti)) < 0)
					_Error(-errcode);
		}							  
		
		loc.l_subs = 2;
		loc.l_sub1 = (USHORT)rowcount;
		loc.l_sub2 = 4;
		// we create an array 
		// this function in version for 8.0 below, can place in the array 16250 words because the array has 4 columns and must have fewer than 65,000 elements.
		// in LCK versions 9.0 this function can place in the array  65000 words a maximum.
		// If is when the quantity of words exceeds the admissible quantity there will be an error message « Too many variables »
		
		if ((nti = _NewVar(varName, &loc, NV_PUBLIC)) < 0)  // or NV_PRIVATE
			_Error(-nti); 		// _NewVar() returns negative Visual FoxPro error number
		
		if (_FindVar(nti, -1, &loc)) {
			if (lasrrowcounforCustomProps)
				DumpBuiltInProps(pPropSetStg, &loc);
			DumpCustomProps(pPropSetStg, &loc, lasrrowcounforCustomProps);
		}
		_HUnLock(parm->p[0].val.ev_handle);
	}
	
	
	// Release obtained interfaces.
	pPropSetStg->Release();
	pStorage->Release();
	// ---------------------	
	
	_RetInt(rowcount, 10);
	return;
}


FoxInfo myFoxInfo[] = {
	{"AGETFILESUMMARY",(FPFI) agetfilesummary, 2, "C,C"},
};

extern "C" {
	FoxTable _FoxTable = {
		(FoxTable FAR *) 0 , sizeof(myFoxInfo) / sizeof(FoxInfo), myFoxInfo
	};
}

Теперь небольшое пояснение, зачем я вообще все это замутил.
Имеется 300 мастерских расположенных по всей Канаде, в которых установлена POS программа на VFP 9.0. Часть операционных систем Windows 2000, остальное Windows XP. Те что на Windows 2000 используют Remote Desktop Connection,
те что на Windows XP используют обычную локальную сеть и технологию файл-сервер, то есть в мастерской имеется сервер и рабочие станции.
Вместе с основной программой есть ряд других вспомогателных программ написанных на VB, .Net. и т.д.
Короче говоря вспомогательные программы устанавливаются из msi файлов.
Нужно одновременно установить программу по всем мастерским.
Толком эта задача так и не была решена, теперь свалили это все на меня.
Проблема в том, что в ночь установки часть компьютеров выключена, на некоторых могут быть проблемы с VPN, с Scheduler Task. Одна из проблем в том, что добиться доступности рабочих станций в ночь установки невозможно.
При этом мои коллеги говорят, о том какая это замечательная вещь msi файлы.
Задачу установки VFP программы я решил элементарно с помощью xcopy.
А вот с msi файлами мне пришлось поломать голову, я решил возложить на VFP задачу установки msi пакетов, каждый раз программа при запуске будет проверять наличие в msi пакетов определенном месте, затем сравнивать версию найденного msi пакета и того же пакета, уже установленного на компьютере, если версии отличаются программа будет устанавливать msi пакет. Для этого мне и нужна была функция позволяющая определить Revision Number msi пакета.
...
Рейтинг: 0 / 0
14.11.2008, 00:19
    #35653194
Jurisfox
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
Игорь2004При этом мои коллеги говорят, о том какая это замечательная вещь msi файлы.
Задачу установки VFP программы я решил элементарно с помощью xcopy.
А вот с msi файлами мне пришлось поломать голову, я решил возложить на VFP задачу установки msi пакетов, каждый раз программа при запуске будет проверять наличие в msi пакетов определенном месте, затем сравнивать версию найденного msi пакета и того же пакета, уже установленного на компьютере, если версии отличаются программа будет устанавливать msi пакет. Для этого мне и нужна была функция позволяющая определить Revision Number msi пакета.

Лучше всего для этой цели подходит технология ClickOnce. Вы можете задать запуск программы
с обязательной проверкой наличия новой версии. Это лучше, чем все инсталляшки.
...
Рейтинг: 0 / 0
14.11.2008, 17:38
    #35655149
Игорь2004
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
to Jurisfox
http://en.wikipedia.org/wiki/ClickOnce
ClickOnce enables the user to install and run a Windows application by just clicking a link in a web page.
Я не могу убедить 300 пользователей кликнуть на ссылке и установить программу, до того как они начнут использовать POS приложение которое нуждается в обновленных вспомогательных приложениях.
Единственное, что пользователи рано или поздно запустят - это POS приложение на VFP.
...
Рейтинг: 0 / 0
14.11.2008, 22:52
    #35655586
Jurisfox
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
Игорь2004to Jurisfox
http://en.wikipedia.org/wiki/ClickOnce
ClickOnce enables the user to install and run a Windows application by just clicking a link in a web page.
Я не могу убедить 300 пользователей кликнуть на ссылке и установить программу, до того как они начнут использовать POS приложение которое нуждается в обновленных вспомогательных приложениях.
Единственное, что пользователи рано или поздно запустят - это POS приложение на VFP.

Вы не поняли сути ClickOnce и тем более способов запуска приложения,
А использовать Википедия для понимания технологии скорее всего бессмысленнo.
Запуск приложения может быть осуществлен с любого источника - CD, сети и Web.
...
Рейтинг: 0 / 0
15.11.2008, 01:27
    #35655711
Sergey Ch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
Если английский знаете, то здесь очень хороший пример как надо обновлять VFP приложение...

Happy reading!
...
Рейтинг: 0 / 0
15.11.2008, 03:29
    #35655733
Jurisfox
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
Sergey ChЕсли английский знаете, то здесь очень хороший пример как надо обновлять VFP приложение...

Happy reading!
Привет Сергей!
По технологии ClickOnce начал серию статей, думаю тебе будет интересно.
Начало:

http://juri.foxhelp.eu/articles/clickonce.aspx

Пример:
http://juri.foxhelp.eu/codedpo/publish.htm

Этот пример загрузит на машину маленькую форму,
которая покажет свободные/занятые ресурсы дисков
имеющихся в клиентской системе.
...
Рейтинг: 0 / 0
15.11.2008, 03:31
    #35655734
Jurisfox
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
JurisfoxПример:
http://juri.foxhelp.eu/codedpo/publish.htm


Ошибся при печати адреса
http://juri.foxhelp.eu/codedepo/publish.htm
...
Рейтинг: 0 / 0
15.11.2008, 05:22
    #35655745
Игорь2004
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
авторВы не поняли сути ClickOnce и тем более способов запуска приложения,
Да, действительно я мельком глянул, на статью и ошибся, данная технология может решить данную задачу, если я смогу убедить коллег, разрабатывающих вспомогательные программы ее использовать (практически нереально), и руководство на это времени не даст. Статья в Wiki дает неплохое описание, я ее просто толком не прочитал.
авторЕсли английский знаете, то здесь очень хороший пример как надо обновлять VFP приложение...
У меня нет проблем с обновлением VFP приложения, я использую xcopy /d в bat файле для запуска VFP приложения, для обновления же вспомогательных программ мне не понадобятся файлы конфигурации, кроме файла с датой и временем, после которого нужно обновить программы, все содержится в системном реестре и в msi пакете. Web я не могу использовать поскольку полоса пропускания будет недостаточной когда несколько десятков пользователей начнут одновременно скачивать файлы, в день когда нужно будет установить обновление, Интернет может и не работать в некоторых мастерских, но у меня будет время чтобы заранее скопировать файлы в локальную сеть каждой мастерской.
Топик кстати был посвящен аналогу функции Agetfileversion но возвращающей другие метаданные.
...
Рейтинг: 0 / 0
15.11.2008, 16:30
    #35656007
Sergey Ch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
Игорь2004... Web я не могу использовать...
Web тут ни причем, этот подход можно использовать с локальными директориями, Intranet etc...

ClickOnce выглядит, конечно более красиво, так как многие вещи делаются одним нажатием кнопки но я применял эту технологию только с .NET приложениями, так как она там по умолчанию... Так что Юрий нашел ей довольно интересное приложение
...
Рейтинг: 0 / 0
15.11.2008, 16:31
    #35656010
Sergey Ch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
Jurisfox Привет Сергей!
Здравствуйте, Юрий!

Написал Вам в приват на FoxClub.
...
Рейтинг: 0 / 0
15.11.2008, 17:45
    #35656046
Игорь2004
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
Код: plaintext
Web тут ни причем, этот подход можно использовать с локальными директориями, Intranet etc... 
Я это прекрасно понял, речь о том, что я не смогу применять Web, а в любом случае придется заранее копировать файлы в локальную (совершенно независимую со своими собственными правами) сеть каждой мастерской, что я сейчас и делаю. Убедить коллег, разрабатывающих вспомогательные программы, я не смогу, на это в любом случае потребуется время, хотя я сам лично с удовольствием повожусь с данной технологией, когда будет время. На VFP я решу ту же задачу несколькими десятками строк кода, функцию AGETFILESUMMARY я адаптировал просто для того чтобы быть в форме, она может быть использована и для других целей, чтение метаданных Word документа etc.
...
Рейтинг: 0 / 0
04.12.2008, 23:38
    #35694994
Игорь2004
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как в VFP узнать информацию о файле (вкладка Summary) ?
Вот небольшая функция, позволяющая получить метаданные о MSI пакете в массив.
Кому нужно может передалать для чтения любых метаданных, ниже ссылки откуда я надергал образцы кода.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
   *** http://forums.microsoft.com/TechNet/ShowPost.aspx?PostID= 3435698 &SiteID= 17 
   *** http://svn.python.org/projects/sandbox/branches/MvL/msi/msilib.py
   *** http://blogs.msdn.com/mwade/archive/ 2006 / 12 / 28 /happy-holidays.aspx
Function GetMsiProperties
   Lparameters lcMsipackage, laProperty
   External Array laProperty
   Local loIns, loDatabaseMSI, loView, loRecord, lnI, lcPropName, lcRes
   lcRes = ""
   If .Not.File(lcMsipackage)
      Return ""
   Endif
   If Type([Createobject("WindowsInstaller.Installer")]) == "O"
      loIns = Createobject("WindowsInstaller.Installer")
      loDatabaseMSI = loIns.OpenDatabase(lcMsipackage,  0 )
      For lnI =  1  To  3 
         Dimension laProperty(lnI,  2 )
         lcPropName = Icase(lnI =  1 , 'ProductName', lnI =  2 , 'ProductCode', lnI =  3 , 'ProductVersion', 'ProductID')
         loView = loDatabaseMSI.OpenView("SELECT Value FROM Property WHERE Property = '"+Alltrim(lcPropName) +"'")
         loView.Execute()
         loRecord = loView.Fetch()
         * ?lcPropName, loRecord.StringData( 1 )
         laProperty(lnI,  1 ) = lcPropName
         laProperty(lnI,  2 ) = loRecord.StringData( 1 )
         * lcRes = lcRes +" "+ lcPropName+" = "+loRecord.StringData( 1 )
      Endfor
      *  loView = loDatabaseMSI.OpenView("SELECT  * FROM Property")  && Property,  Value,
      *  loView = loDatabaseMSI.OpenView("SELECT  * FROM _Tables")  && all tables
      *!*	      loView.Execute()
      *!*	      loRecord = loView.Fetch()
      *!*	      Do While .Not.Isnull(loRecord)
      *!*	         ?loRecord.StringData( 1 ), loRecord.StringData( 2 ), loRecord.StringData( 3 ),  loRecord.StringData( 4 )
      *!*	         loRecord = loView.Fetch()
      *!*	      Enddo
      loView.Close()
      Store Null To loRecord,  loView, loDatabaseMSI, loIns
   Endif
   * Return lcRes
...
Рейтинг: 0 / 0
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Как в VFP узнать информацию о файле (вкладка Summary) ? / 16 сообщений из 16, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]